我需要从外部包装类中更改包装私有类中的私有变量的值。
我尝试过:
private void writePrivateJarVerifierField(boolean newValue) throws Exception {
Class<?> clazz = Class.forName("java.util.jar.JarVerifier");
Field field = clazz.getDeclaredField("parsingBlockOrSF");
field.setAccessible(true);
field.setBoolean(clazz.newInstance(), newValue);
}
它给了我Exception in thread "main" java.lang.InstantiationException: java.util.jar.JarVerifier
尽管我无法为我的问题提供解决方案,但我已经看到this,this,this和this问题。
有人可以给我一个提示吗?
编辑1:,因为我想在运行时修改parsingBlockOrSF的值(就像我通过调试器更改了一样),因此我需要一个JarVerifier实例,因此需要一个JarFile实例(感谢Gyro Gearless)看看Ankur Chrungoo提出的方法,我发现我需要获取一个已经存在的JarVerifier实例,因此我尝试了以下方法:
private void writePrivateJarVerifierField(boolean newValue, JarFile jf) throws Exception {
Class<?> clazz = Class.forName("java.util.jar.JarVerifier");
Class<?> clacc = Class.forName("java.util.jar.JarFile");
Field field = clazz.getDeclaredField("parsingBlockOrSF");
Field field1 = clacc.getDeclaredField("jv");
field.setAccessible(true);
field1.setAccessible(true);
field.setBoolean(field1.get(jf), newValue);
}
JarFile jf在其中创建JarVerifier的新实例并将其保存在名为jv的变量中。这就是为什么我旨在同时获得两个类JarVerifier和JarFile的原因,以便同时获得两个我想访问的变量(一个从JarVerifier获取实际的布尔parsingBlockOrSF,另一个从JarFile实例获取jarVerifier实例jv。在我看来,上面显示的代码有意义并且应该可以工作,但是没有,所以我的错误在哪里?
我得到的异常:java.lang.NullPointerException at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:57)
编辑2:,将上述代码的最后一行更改为:
field.setBoolean(field1.getType(), newValue);
尽管Can not set boolean field java.util.jar.JarVerifier.parsingBlockOrSF to java.lang.Class
编辑3:,使用此代码:
Class<?> clazz = Class.forName("java.util.jar.JarVerifier");
Class<?> clacc = Class.forName("java.util.jar.JarFile");
Field field = clazz.getDeclaredField("parsingBlockOrSF");
Field field1 = clacc.getDeclaredField("jv");
field.setAccessible(true);
field1.setAccessible(true);
field.setBoolean(clazz.getConstructor(byte[].class).newInstance(new byte[1]), newValue);
我收到此错误:Exception in thread "main" java.lang.IllegalAccessException: class JarVerifier cannot access a member of class java.util.jar.JarVerifier (in module java.base) with modifiers "public"
这里我想在JarFile内的jarVerifier中更改parsingBlockOrSF的值,所以我首先必须在jarFile实例上工作,将jarVerifier移出该实例(我试图用field1 = calcc.getDeclaredField( “ jv”),因为jarVerifier存储在JarFile的jv变量中),然后使用该对象修改其属性
创建JarFile的代码:
JarFile jf = null;
jf = new JarFile(jarName, true);
jarName是一个字符串,代表.jar文件的路径
答案 0 :(得分:2)
我可以看到JarVerifier类没有默认的构造方法。 它具有的构造函数是这样的:-
public JarVerifier(byte rawBytes[]) {
manifestRawBytes = rawBytes;
sigFileSigners = new Hashtable<>();
verifiedSigners = new Hashtable<>();
sigFileData = new Hashtable<>(11);
pendingBlocks = new ArrayList<>();
baos = new ByteArrayOutputStream();
manifestDigests = new ArrayList<>();
}
因此,您将必须使用反射获取非默认构造函数,然后使用它来创建实例。 因此,您的代码应如下所示:-
field.setBoolean(clazz.getConstructor(byte[].class).newInstance(new byte[1]), newValue);
JarVerifier类的参考:https://github.com/netroby/jdk9-dev/blob/master/jdk/src/java.base/share/classes/java/util/jar/JarVerifier.java
假设:您的应用程序具有必需的安全权限,可以使用反射来修改访问。
更多参考:Java: newInstance of class that has no default constructor
答案 1 :(得分:0)
您不能从java.lang和java.util.jar包更改对象。这些软件包是系统软件包,如果不能更改,则受jvm保护。