Add comments regarding Java 1.8 byte code level for CGLIB
Unfortunately, it is not possible to raise the byte code level beyond Java 1.8 for classes generated using CGLIB due to the fact that CGLIB generates STATICHOOK methods which set static final fields outside the initializer method <clinit> (i.e., a static initialization block). Attempting to raise the level to Java 17 (or even Java 9) results in exceptions like the following. Caused by: java.lang.IllegalAccessError: Update to static final field org.example.MyBean$$SpringCGLIB$$0.CGLIB$THREAD_CALLBACKS attempted from a different method (CGLIB$STATICHOOK1) than the initializer method <clinit> at org.example.MyBean$$SpringCGLIB$$0.CGLIB$STATICHOOK1(<generated>) at org.example.MyBean$$SpringCGLIB$$0.<clinit>(<generated>) This commit therefore introduces inline comments pointing out why we stay with Java 1.8 byte code level with CGLIB. See gh-34602
This commit is contained in:
parent
a0763d13c5
commit
d6a7aefd1d
|
@ -116,6 +116,8 @@ abstract public class BeanCopier
|
|||
Type sourceType = Type.getType(source);
|
||||
Type targetType = Type.getType(target);
|
||||
ClassEmitter ce = new ClassEmitter(v);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
|
@ -117,6 +117,8 @@ public class BeanGenerator extends AbstractClassGenerator
|
|||
types[i] = (Type)props.get(names[i]);
|
||||
}
|
||||
ClassEmitter ce = new ClassEmitter(v);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
|
@ -57,6 +57,8 @@ class BeanMapEmitter extends ClassEmitter {
|
|||
public BeanMapEmitter(ClassVisitor v, String className, Class type, int require) {
|
||||
super(v);
|
||||
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE);
|
||||
EmitUtils.null_constructor(this);
|
||||
EmitUtils.factory_method(this, NEW_INSTANCE);
|
||||
|
|
|
@ -56,6 +56,8 @@ class BulkBeanEmitter extends ClassEmitter {
|
|||
Method[] setters = new Method[setterNames.length];
|
||||
validate(target, getterNames, setterNames, types, getters, setters);
|
||||
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, BULK_BEAN, null, Constants.SOURCE_FILE);
|
||||
EmitUtils.null_constructor(this);
|
||||
generateGet(target, getters);
|
||||
|
|
|
@ -89,6 +89,8 @@ public class ImmutableBean
|
|||
public void generateClass(ClassVisitor v) {
|
||||
Type targetType = Type.getType(target);
|
||||
ClassEmitter ce = new ClassEmitter(v);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
|
@ -261,6 +261,8 @@ abstract public class KeyFactory {
|
|||
}
|
||||
|
||||
Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
|
@ -678,6 +678,8 @@ public class Enhancer extends AbstractClassGenerator {
|
|||
|
||||
ClassEmitter e = new ClassEmitter(v);
|
||||
if (currentData == null) {
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
e.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
@ -688,6 +690,8 @@ public class Enhancer extends AbstractClassGenerator {
|
|||
Constants.SOURCE_FILE);
|
||||
}
|
||||
else {
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
e.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
|
@ -94,23 +94,25 @@ public class InterfaceMaker extends AbstractClassGenerator
|
|||
}
|
||||
|
||||
@Override
|
||||
protected ClassLoader getDefaultClassLoader() {
|
||||
protected ClassLoader getDefaultClassLoader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object firstInstance(Class type) {
|
||||
protected Object firstInstance(Class type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object nextInstance(Object instance) {
|
||||
protected Object nextInstance(Object instance) {
|
||||
throw new IllegalStateException("InterfaceMaker does not cache");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generateClass(ClassVisitor v) throws Exception {
|
||||
public void generateClass(ClassVisitor v) throws Exception {
|
||||
ClassEmitter ce = new ClassEmitter(v);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC | Constants.ACC_INTERFACE | Constants.ACC_ABSTRACT,
|
||||
getClassName(),
|
||||
|
|
|
@ -48,6 +48,8 @@ class MixinEmitter extends ClassEmitter {
|
|||
public MixinEmitter(ClassVisitor v, String className, Class[] classes, int[] route) {
|
||||
super(v);
|
||||
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
className,
|
||||
|
|
|
@ -105,6 +105,8 @@ abstract public class ConstructorDelegate {
|
|||
}
|
||||
|
||||
ClassEmitter ce = new ClassEmitter(v);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
|
@ -75,6 +75,8 @@ class FastClassEmitter extends ClassEmitter {
|
|||
super(v);
|
||||
|
||||
Type base = Type.getType(type);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, FAST_CLASS, null, Constants.SOURCE_FILE);
|
||||
|
||||
// constructor
|
||||
|
|
|
@ -236,6 +236,8 @@ abstract public class MethodDelegate {
|
|||
|
||||
ClassEmitter ce = new ClassEmitter(v);
|
||||
CodeEmitter e;
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
|
@ -117,6 +117,8 @@ abstract public class MulticastDelegate implements Cloneable {
|
|||
final MethodInfo method = ReflectUtils.getMethodInfo(ReflectUtils.findInterfaceMethod(iface));
|
||||
|
||||
ClassEmitter ce = new ClassEmitter(cv);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
|
@ -38,6 +38,8 @@ class ParallelSorterEmitter extends ClassEmitter {
|
|||
|
||||
public ParallelSorterEmitter(ClassVisitor v, String className, Object[] arrays) {
|
||||
super(v);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, PARALLEL_SORTER, null, Constants.SOURCE_FILE);
|
||||
EmitUtils.null_constructor(this);
|
||||
EmitUtils.factory_method(this, NEW_INSTANCE);
|
||||
|
|
|
@ -133,6 +133,8 @@ abstract public class StringSwitcher {
|
|||
@Override
|
||||
public void generateClass(ClassVisitor v) throws Exception {
|
||||
ClassEmitter ce = new ClassEmitter(v);
|
||||
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
|
||||
// which set static final fields outside the initializer method <clinit>.
|
||||
ce.begin_class(Constants.V1_8,
|
||||
Constants.ACC_PUBLIC,
|
||||
getClassName(),
|
||||
|
|
Loading…
Reference in New Issue