Establecer campo privado de Clase paquete-privada cubierta externa Clase con la reflexión

Nicolas Brauer:

Necesito cambiar el valor de una variable privada en una clase de paquete-privada de una clase-envase exterior.

  • Paquete: java.util.jar de JDK-9.0.1
  • clase: JarVerifier.java
  • variables: parsingBlockOrSF (private boolean)

He intentado esto:

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);
}

Me da Exception in thread "main" java.lang.InstantiationException: java.util.jar.JarVerifier

He visto esta , esta , esta y esta pregunta ya, aunque no soy capaz de obtener una solución para mi problema.

Alguien me puede dar una pista por favor?


Editar 1: como quiera modificar el valor de parsingBlockOrSF durante el tiempo de ejecución (como si lo cambié a través depurador) Necesito una instancia existente de JarVerifier tanto de JarFile (gracias Gyro sin engranaje) Al echar un vistazo en el enfoque propuesto por Ankur Chrungoo , me di cuenta de que iba a necesitar para obtener una instancia ya existente de JarVerifier, por tanto, he intentado esto:

    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);
}

Cuando el jf JarFile crea una nueva instancia de JarVerifier y lo guarda en la variable llamada JV. Es por eso que estoy con el objetivo de conseguir ambas clases JarVerifier y JarFile, con el fin de conseguir tanto la variable quiero acceso (una beeing la parsingBlockOrSF booleano real de la JarVerifier, el otro beeing la empresa conjunta ejemplo JarVerifier de la instancia JarFile. En mi opinión, la codigo de arriba tiene sentido y debería funcionar, pero no es así, ¿dónde está mi error?

La excepción consigo: java.lang.NullPointerException at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:57)


Edición 2: cambiar la última línea del código anterior a:field.setBoolean(field1.getType(), newValue);

Parece que se reconoce el objeto, aunque Can not set boolean field java.util.jar.JarVerifier.parsingBlockOrSF to java.lang.Class


Datos 3: mediante el uso de este Código:

    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);

Me sale este error: 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"

Aquí quiero cambiar el valor de la parsingBlockOrSF en el interior de la jarVerifier JarFile, por lo que la primera obra obligada en la instancia archivoJar, sale el jarVerifier fuera de ella (lo que yo estoy tratando de hacer con campo1 = calcc.getDeclaredField ( "JV" ) como el jarVerifier se almacena en la variable jv dentro de la JarFile), y después usando ese objeto, modificar su propiedad


El Código donde se crea el JarFile:

    JarFile jf = null;
    jf = new JarFile(jarName, true);

jarName es una cadena que representa la ruta de acceso al archivo .jar

Ankur Chrungoo:

Pude ver que la clase JarVerifier no tiene un constructor por defecto. El constructor que tiene es algo como esto: -

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<>();
    }

Por lo tanto, tendría que obtener el constructor no predeterminado utilizando la reflexión y luego utilizarlo para crear la instancia. Por lo tanto, el código debe ser algo como esto: -

field.setBoolean(clazz.getConstructor(byte[].class).newInstance(new byte[1]), newValue);

Referencia para la clase JarVerifier: https://github.com/netroby/jdk9-dev/blob/master/jdk/src/java.base/share/classes/java/util/jar/JarVerifier.java

Supuesto: Su aplicación tiene los permisos de seguridad necesarios para modificar el acceso utilizando la reflexión.

Además referencia: Java: newInstance de la clase que no tiene un constructor por defecto

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=235892&siteId=1
Recomendado
Clasificación