JDK16之后限制了反射方式对于JDK内部类的访问,因此在使用高版本JDK运行较低版本的JDK时,某些依赖由于会发生错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class SimpleClass {
private String foo = "foo";
public String getFoo() {
return foo;
}
}

public class Main {
// 反射访问和修改非JDK内部类SimpleClass
public static class ReflectSimpleClass {
private void changeFoo(SimpleClass simpleClass) {
try {
Field fooField = SimpleClass.class.getDeclaredField("foo");
fooField.setAccessible(true);
fooField.set(simpleClass, "bar");
} catch (NoSuchFieldException | IllegalAccessException e) {
System.out.println(e.getMessage());
}
}
}
// 反射访问和修改JDK内部类ArrayList
public static class ReflectInternalClass {
private<T> void changeSize(ArrayList<T> arrayList) {
try {
Field sizeField = ArrayList.class.getDeclaredField("size");
sizeField.setAccessible(true);
sizeField.set(arrayList, 114514);
} catch (NoSuchFieldException | IllegalAccessException e) {
System.out.println(e.getMessage());
}
}
}
public static void main(String[] args) {
// 分别测试对JDK内部类和非JDK内部类的反射访问和修改,从JDK16开始,修改JDK内部类的属性则会报错
// 测试结果:若JDK版本是8,可以修改JDK内部类的属性;若JDK版本是17,则不行。
// 修改运行时的JDK版本的方法:Main->Edit Configuration->Build and Run
SimpleClass simpleClass = new SimpleClass();
System.out.println(simpleClass.getFoo());
new ReflectSimpleClass().changeFoo(simpleClass);
// 预期输出:bar
System.out.println(simpleClass.getFoo());
// 测试对JDK内部类的反射访问和修改
ArrayList<Integer> arrayList = new ArrayList();
System.out.println(arrayList.size());
new ReflectInternalClass().changeSize(arrayList);
// 预期输出:114514
System.out.println(arrayList.size());
}
}

解决方案:

通过添加 JVM 参数来开放模块对 cglib 所需方法的访问权限。具体来说,可以在Idea中的Edit Configuration->VM options中添加以下参数:

--add-opens java.base/java.lang=ALL-UNNAMED

__END__