Skip to content

Commit d6a7aef

Browse files
committed
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
1 parent a0763d1 commit d6a7aef

15 files changed

+36
-4
lines changed

Diff for: spring-core/src/main/java/org/springframework/cglib/beans/BeanCopier.java

+2
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ public void generateClass(ClassVisitor v) {
116116
Type sourceType = Type.getType(source);
117117
Type targetType = Type.getType(target);
118118
ClassEmitter ce = new ClassEmitter(v);
119+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
120+
// which set static final fields outside the initializer method <clinit>.
119121
ce.begin_class(Constants.V1_8,
120122
Constants.ACC_PUBLIC,
121123
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/beans/BeanGenerator.java

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ public void generateClass(ClassVisitor v) throws Exception {
117117
types[i] = (Type)props.get(names[i]);
118118
}
119119
ClassEmitter ce = new ClassEmitter(v);
120+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
121+
// which set static final fields outside the initializer method <clinit>.
120122
ce.begin_class(Constants.V1_8,
121123
Constants.ACC_PUBLIC,
122124
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/beans/BeanMapEmitter.java

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ class BeanMapEmitter extends ClassEmitter {
5757
public BeanMapEmitter(ClassVisitor v, String className, Class type, int require) {
5858
super(v);
5959

60+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
61+
// which set static final fields outside the initializer method <clinit>.
6062
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE);
6163
EmitUtils.null_constructor(this);
6264
EmitUtils.factory_method(this, NEW_INSTANCE);

Diff for: spring-core/src/main/java/org/springframework/cglib/beans/BulkBeanEmitter.java

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ public BulkBeanEmitter(ClassVisitor v,
5656
Method[] setters = new Method[setterNames.length];
5757
validate(target, getterNames, setterNames, types, getters, setters);
5858

59+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
60+
// which set static final fields outside the initializer method <clinit>.
5961
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, BULK_BEAN, null, Constants.SOURCE_FILE);
6062
EmitUtils.null_constructor(this);
6163
generateGet(target, getters);

Diff for: spring-core/src/main/java/org/springframework/cglib/beans/ImmutableBean.java

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public Object create() {
8989
public void generateClass(ClassVisitor v) {
9090
Type targetType = Type.getType(target);
9191
ClassEmitter ce = new ClassEmitter(v);
92+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
93+
// which set static final fields outside the initializer method <clinit>.
9294
ce.begin_class(Constants.V1_8,
9395
Constants.ACC_PUBLIC,
9496
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/core/KeyFactory.java

+2
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ public void generateClass(ClassVisitor v) {
261261
}
262262

263263
Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
264+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
265+
// which set static final fields outside the initializer method <clinit>.
264266
ce.begin_class(Constants.V1_8,
265267
Constants.ACC_PUBLIC,
266268
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/proxy/Enhancer.java

+4
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,8 @@ public void generateClass(ClassVisitor v) throws Exception {
678678

679679
ClassEmitter e = new ClassEmitter(v);
680680
if (currentData == null) {
681+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
682+
// which set static final fields outside the initializer method <clinit>.
681683
e.begin_class(Constants.V1_8,
682684
Constants.ACC_PUBLIC,
683685
getClassName(),
@@ -688,6 +690,8 @@ public void generateClass(ClassVisitor v) throws Exception {
688690
Constants.SOURCE_FILE);
689691
}
690692
else {
693+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
694+
// which set static final fields outside the initializer method <clinit>.
691695
e.begin_class(Constants.V1_8,
692696
Constants.ACC_PUBLIC,
693697
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/proxy/InterfaceMaker.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -94,23 +94,25 @@ public Class create() {
9494
}
9595

9696
@Override
97-
protected ClassLoader getDefaultClassLoader() {
97+
protected ClassLoader getDefaultClassLoader() {
9898
return null;
9999
}
100100

101101
@Override
102-
protected Object firstInstance(Class type) {
102+
protected Object firstInstance(Class type) {
103103
return type;
104104
}
105105

106106
@Override
107-
protected Object nextInstance(Object instance) {
107+
protected Object nextInstance(Object instance) {
108108
throw new IllegalStateException("InterfaceMaker does not cache");
109109
}
110110

111111
@Override
112-
public void generateClass(ClassVisitor v) throws Exception {
112+
public void generateClass(ClassVisitor v) throws Exception {
113113
ClassEmitter ce = new ClassEmitter(v);
114+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
115+
// which set static final fields outside the initializer method <clinit>.
114116
ce.begin_class(Constants.V1_8,
115117
Constants.ACC_PUBLIC | Constants.ACC_INTERFACE | Constants.ACC_ABSTRACT,
116118
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/proxy/MixinEmitter.java

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ class MixinEmitter extends ClassEmitter {
4848
public MixinEmitter(ClassVisitor v, String className, Class[] classes, int[] route) {
4949
super(v);
5050

51+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
52+
// which set static final fields outside the initializer method <clinit>.
5153
begin_class(Constants.V1_8,
5254
Constants.ACC_PUBLIC,
5355
className,

Diff for: spring-core/src/main/java/org/springframework/cglib/reflect/ConstructorDelegate.java

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ public void generateClass(ClassVisitor v) {
105105
}
106106

107107
ClassEmitter ce = new ClassEmitter(v);
108+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
109+
// which set static final fields outside the initializer method <clinit>.
108110
ce.begin_class(Constants.V1_8,
109111
Constants.ACC_PUBLIC,
110112
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/reflect/FastClassEmitter.java

+2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public FastClassEmitter(ClassVisitor v, String className, Class type) {
7575
super(v);
7676

7777
Type base = Type.getType(type);
78+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
79+
// which set static final fields outside the initializer method <clinit>.
7880
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, FAST_CLASS, null, Constants.SOURCE_FILE);
7981

8082
// constructor

Diff for: spring-core/src/main/java/org/springframework/cglib/reflect/MethodDelegate.java

+2
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ public void generateClass(ClassVisitor v) throws NoSuchMethodException {
236236

237237
ClassEmitter ce = new ClassEmitter(v);
238238
CodeEmitter e;
239+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
240+
// which set static final fields outside the initializer method <clinit>.
239241
ce.begin_class(Constants.V1_8,
240242
Constants.ACC_PUBLIC,
241243
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/reflect/MulticastDelegate.java

+2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ public void generateClass(ClassVisitor cv) {
117117
final MethodInfo method = ReflectUtils.getMethodInfo(ReflectUtils.findInterfaceMethod(iface));
118118

119119
ClassEmitter ce = new ClassEmitter(cv);
120+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
121+
// which set static final fields outside the initializer method <clinit>.
120122
ce.begin_class(Constants.V1_8,
121123
Constants.ACC_PUBLIC,
122124
getClassName(),

Diff for: spring-core/src/main/java/org/springframework/cglib/util/ParallelSorterEmitter.java

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class ParallelSorterEmitter extends ClassEmitter {
3838

3939
public ParallelSorterEmitter(ClassVisitor v, String className, Object[] arrays) {
4040
super(v);
41+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
42+
// which set static final fields outside the initializer method <clinit>.
4143
begin_class(Constants.V1_8, Constants.ACC_PUBLIC, className, PARALLEL_SORTER, null, Constants.SOURCE_FILE);
4244
EmitUtils.null_constructor(this);
4345
EmitUtils.factory_method(this, NEW_INSTANCE);

Diff for: spring-core/src/main/java/org/springframework/cglib/util/StringSwitcher.java

+2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ public StringSwitcher create() {
133133
@Override
134134
public void generateClass(ClassVisitor v) throws Exception {
135135
ClassEmitter ce = new ClassEmitter(v);
136+
// Byte code level cannot be higher than 1.8 due to STATICHOOK methods
137+
// which set static final fields outside the initializer method <clinit>.
136138
ce.begin_class(Constants.V1_8,
137139
Constants.ACC_PUBLIC,
138140
getClassName(),

0 commit comments

Comments
 (0)