前言
学习,听说Java9环境下defineClass会被拦截。
环境
JDK9.0.4
TemplatesImpl
既然defineClass会有问题,那TemplatesImpl也会有问题。
但是尝试实例化TemplatesImpl类时发现出现了编译报错问题:
Error:(3, 41) java: 程序包 com.sun.org.apache.xalan.internal.xsltc 不可见
(程序包 com.sun.org.apache.xalan.internal.xsltc 已在模块 java.xml 中声明, 但该模块未导出它)
看起来是TemplatesImpl类被官方给黑名单了,根据描述在java.xml包下能找到module-info.java文件,里面定义了java.xml模块和包下所有导出的类,里面并不包括TemplatesImpl类,想要使用似乎要在编译设置中额外配置将其导出。
尝试通过反射实例化,然后反射调用函数,似乎没有问题:
Class<?> cls = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");
Object templates = cls.newInstance();
Class<?> cls2 = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
Object factory = cls2.newInstance();
setField(templates, "_name", "Twings");
setField(templates, "_bytecodes", new byte[][]{bytes});
setField(templates, "_tfactory", factory);
Method m = cls.getDeclaredMethod("getOutputProperties");
m.invoke(templates);
但是会报出警告:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.example.App (file:/D:/Java1.8/Java9/target/classes/) to field com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl._name
WARNING: Please consider reporting this to the maintainers of org.example.App
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
看起来该版本下对以往版本中为所欲为的反射操作有了警告,类似Field.set等操作都会被警告。
defineClass
defineClass也是反射,也同样会有警告:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.example.App (file:/D:/Java1.8/Java9/target/classes/) to method java.lang.ClassLoader.defineClass(byte[],int,int)
WARNING: Please consider reporting this to the maintainers of org.example.App
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
可以使用Unsafe的defineAnonymousClass函数绕过这个问题:
Class<?> cls = Class.forName("sun.misc.Unsafe");
Field field = getField(cls, "theUnsafe");
Object unSafe = field.get(null);
Method method = unSafe.getClass().getDeclaredMethod("defineAnonymousClass", Class.class, byte[].class, Object[].class);
Class<?> c = (Class<?>)method.invoke(unSafe, new Object[]{Runtime.class, bytes, null});
c.newInstance();
不过要注意跟模板类所属包的问题。
参考
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!