Skip to content
Commits on Source (6)
......@@ -9,7 +9,7 @@
<parent>
<groupId>cglib</groupId>
<artifactId>cglib-parent</artifactId>
<version>3.2.9</version>
<version>3.2.10</version>
</parent>
<!-- ====================================================================== -->
......
......@@ -7,7 +7,7 @@
<parent>
<artifactId>cglib-parent</artifactId>
<groupId>cglib</groupId>
<version>3.2.9</version>
<version>3.2.10</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
......@@ -9,7 +9,7 @@
<parent>
<groupId>cglib</groupId>
<artifactId>cglib-parent</artifactId>
<version>3.2.9</version>
<version>3.2.10</version>
</parent>
<!-- ====================================================================== -->
......
......@@ -9,7 +9,7 @@
<parent>
<groupId>cglib</groupId>
<artifactId>cglib-parent</artifactId>
<version>3.2.9</version>
<version>3.2.10</version>
</parent>
<!-- ====================================================================== -->
......
......@@ -9,7 +9,7 @@
<parent>
<groupId>cglib</groupId>
<artifactId>cglib-parent</artifactId>
<version>3.2.9</version>
<version>3.2.10</version>
</parent>
<!-- ====================================================================== -->
......
......@@ -56,7 +56,7 @@ class BulkBeanEmitter extends ClassEmitter {
private void generateGet(final Class target, final Method[] getters) {
CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_VALUES, null);
if (getters.length >= 0) {
if (getters.length > 0) {
e.load_arg(0);
e.checkcast(Type.getType(target));
Local bean = e.make_local();
......
......@@ -39,13 +39,16 @@ implements ClassGenerator
private static volatile Map<ClassLoader, ClassLoaderData> CACHE = new WeakHashMap<ClassLoader, ClassLoaderData>();
private static final boolean DEFAULT_USE_CACHE =
Boolean.parseBoolean(System.getProperty("cglib.useCache", "true"));
private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;
private NamingPolicy namingPolicy = DefaultNamingPolicy.INSTANCE;
private Source source;
private ClassLoader classLoader;
private String namePrefix;
private Object key;
private boolean useCache = true;
private boolean useCache = DEFAULT_USE_CACHE;
private String className;
private boolean attemptLoad;
......
......@@ -22,18 +22,20 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import net.sf.cglib.core.Constants;
import net.sf.cglib.core.Signature;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* Uses bytecode reflection to figure out the targets of all bridge methods
* that use invokespecial, so that we can later rewrite them to use invokevirtual.
* Uses bytecode reflection to figure out the targets of all bridge methods that use invokespecial
* and invokeinterface, so that we can later rewrite them to use invokevirtual.
*
* <p>For interface bridges, using invokesuper will fail since the method being bridged to is in a
* superinterface, not a superclass. Starting in Java 8, javac emits default bridge methods in
* interfaces, which use invokeinterface to bridge to the target method.
*
* @author sberlin@gmail.com (Sam Berlin)
*/
......@@ -96,9 +98,11 @@ class BridgeMethodResolver {
if (eligibleMethods.remove(sig)) {
currentMethod = sig;
return new MethodVisitor(Constants.ASM_API) {
public void visitMethodInsn(int opcode, String owner, String name,
String desc, boolean itf) {
if (opcode == Opcodes.INVOKESPECIAL && currentMethod != null) {
public void visitMethodInsn(
int opcode, String owner, String name, String desc, boolean itf) {
if ((opcode == Opcodes.INVOKESPECIAL
|| (itf && opcode == Opcodes.INVOKEINTERFACE))
&& currentMethod != null) {
Signature target = new Signature(name, desc);
// If the target signature is the same as the current,
// we shouldn't change our bridge becaues invokespecial
......
......@@ -1418,6 +1418,163 @@ public class TestEnhancer extends CodeGenTestCase {
assertEquals(Arrays.asList(Object.class, String.class), paramTypes);
}
public void testInterfaceBridge() throws Exception {
// recent versions of javac will generate a synthetic default bridge for f(Object) in B
// interface A<T> {
// void f(T t);
// }
// interface B<T extends Number> extends A<T>{
// void f(T t);
// }
if (getMajor() < 8) {
// The test relies on Java 8 bytecode for default methods.
return;
}
final Map<String, byte[]> classes = new HashMap<String, byte[]>();
{
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(
Opcodes.V1_8,
Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_PUBLIC,
"A",
"<T:Ljava/lang/Object;>Ljava/lang/Object;",
"java/lang/Object",
null);
MethodVisitor methodVisitor =
classWriter.visitMethod(
Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
"f",
"(Ljava/lang/Object;)V",
"(TT;)V",
null);
methodVisitor.visitEnd();
classWriter.visitEnd();
classes.put("A.class", classWriter.toByteArray());
}
{
ClassWriter classWriter = new ClassWriter(0);
classWriter.visit(
Opcodes.V1_8,
Opcodes.ACC_ABSTRACT | Opcodes.ACC_INTERFACE | Opcodes.ACC_PUBLIC,
"B",
"<T:Ljava/lang/Number;>Ljava/lang/Object;LA<TT;>;",
"java/lang/Object",
new String[] {"A"});
{
MethodVisitor methodVisitor =
classWriter.visitMethod(
Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT,
"f",
"(Ljava/lang/Number;)V",
"(TT;)V",
null);
methodVisitor.visitEnd();
}
{
MethodVisitor methodVisitor =
classWriter.visitMethod(
Opcodes.ACC_PUBLIC | Opcodes.ACC_BRIDGE | Opcodes.ACC_SYNTHETIC,
"f",
"(Ljava/lang/Object;)V",
null,
null);
methodVisitor.visitCode();
methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/Number");
methodVisitor.visitMethodInsn(
Opcodes.INVOKEINTERFACE, "B", "f", "(Ljava/lang/Number;)V", true);
methodVisitor.visitInsn(Opcodes.RETURN);
methodVisitor.visitMaxs(2, 2);
methodVisitor.visitEnd();
}
classWriter.visitEnd();
classes.put("B.class", classWriter.toByteArray());
}
ClassLoader classLoader =
new ClassLoader(getClass().getClassLoader()) {
@Override
public InputStream getResourceAsStream(String name) {
InputStream is = super.getResourceAsStream(name);
if (is != null) {
return is;
}
if (classes.containsKey(name)) {
return new ByteArrayInputStream(classes.get(name));
}
return null;
}
public Class findClass(String name) throws ClassNotFoundException {
byte[] ba = classes.get(name.replace('.', '/') + ".class");
if (ba != null) {
return defineClass(name, ba, 0, ba.length);
}
throw new ClassNotFoundException(name);
}
};
final List<Class> paramTypes = new ArrayList<Class>();
Enhancer e = new Enhancer();
e.setClassLoader(classLoader);
e.setInterfaces(new Class[] {classLoader.loadClass("B")});
e.setCallbackFilter(
new CallbackFilter() {
public int accept(Method method) {
return method.isBridge() ? 1 : 0;
}
});
e.setCallbacks(
new Callback[] {
new MethodInterceptor() {
public Object intercept(
Object obj, Method method, Object[] args, MethodProxy proxy) {
if (method.getParameterTypes().length > 0) {
paramTypes.add(method.getParameterTypes()[0]);
}
return null;
}
},
NoOp.INSTANCE
});
Object c = e.create();
for (Method m : classLoader.loadClass("A").getDeclaredMethods()) {
if (m.getName().equals("f")) {
m.invoke(c, new Object[] {null});
}
}
// f(Object)void should bridge to f(Number)void
assertEquals(Arrays.asList(Number.class), paramTypes);
}
private static int getMajor() {
try {
Method versionMethod = Runtime.class.getMethod("version");
Object version = versionMethod.invoke(null);
return (Integer) version.getClass().getMethod("major").invoke(version);
} catch (Exception e) {
// continue below
}
int version = (int) Double.parseDouble(System.getProperty("java.class.version"));
if (49 <= version && version <= 52) {
return version - (49 - 5);
}
throw new IllegalStateException(
"Unknown Java version: " + System.getProperty("java.specification.version"));
}
static class ErasedType {}
static class RetType extends ErasedType {}
static class Refined extends RetType {}
......
cglib (3.2.10-1) unstable; urgency=medium
* Team upload.
* New upstream release
* Standards-Version updated to 4.3.0
* Use salsa.debian.org Vcs-* URLs
-- Emmanuel Bourg <ebourg@apache.org> Sun, 06 Jan 2019 01:11:54 +0100
cglib (3.2.9-1) unstable; urgency=medium
* Team upload.
......
......@@ -3,7 +3,8 @@ Section: java
Priority: optional
Maintainer: Debian Java Maintainers <pkg-java-maintainers@lists.alioth.debian.org>
Uploaders: Emmanuel Bourg <ebourg@apache.org>
Build-Depends: ant,
Build-Depends:
ant,
debhelper (>= 11),
default-jdk,
junit4,
......@@ -11,9 +12,9 @@ Build-Depends: ant,
libjarjar-maven-plugin-java,
libmaven-javadoc-plugin-java,
maven-debian-helper (>= 2.0.4)
Standards-Version: 4.2.1
Vcs-Git: https://anonscm.debian.org/git/pkg-java/cglib.git
Vcs-Browser: https://anonscm.debian.org/cgit/pkg-java/cglib.git
Standards-Version: 4.3.0
Vcs-Git: https://salsa.debian.org/java-team/cglib.git
Vcs-Browser: https://salsa.debian.org/java-team/cglib
Homepage: http://cglib.sourceforge.net
Package: libcglib-java
......
......@@ -14,7 +14,7 @@
<!-- ====================================================================== -->
<groupId>cglib</groupId>
<artifactId>cglib-parent</artifactId>
<version>3.2.9</version>
<version>3.2.10</version>
<packaging>pom</packaging>
<name>Code Generation Library</name>
......