Quisiera invocar un método privado sin necesidad de utilizar la reflexión: ¿es posible conectar un método nativo privada mediante el uso de ASM y la invocan?
El reto no es generar una clase de invocar el private
método a través ASM o una herramienta de generación de código de bytes similar. El reto es conseguir que el código de bytes en la JVM sin ser rechazado por el verificador.
Para OpenJDK / HotSpot, hay sun.misc.Unsafe
que tiene el método defineAnonymousClass(Class<?>, byte[], Object[])
que se utiliza para generar clases de descriptor de acceso, como las clases de ejecución implementar interfaces funcionales e invocando los private
métodos sintéticos que sostienen el cuerpo de una expresión lambda.
Usted puede usar esto para cargar el código de bytes, utilizando la private
clase de declarar el método como primer argumento, para hacer que el método de acceso. Por otra parte, el propio caso de uso de la JRE implica que usted ni siquiera necesita para generar tales código de bytes a sí mismo:
MethodHandles.Lookup l = MethodHandles.privateLookupIn(Class.class, MethodHandles.lookup());
MethodHandle target = l.findSpecial(Class.class, "getDeclaredFields0",
MethodType.methodType(Field[].class, boolean.class), Class.class);
BiFunction<Class<?>,Boolean,Field[]> a = (BiFunction)LambdaMetafactory.metafactory(
l, "apply", MethodType.methodType(BiFunction.class), target.type().generic(),
target, target.type().changeParameterType(1, Boolean.class))
.getTarget().invokeExact();
A continuación, se puede llamar, por ejemplo, a.apply(Class.class, false)
que invocará getDeclaredFields0
sin reflexión.
privateLookupIn
9 es un método Java que funcionará si estás en código no modular o proporcionar la necesaria --add-opens
opción al inicio de la JVM, para abrir java.base
a su módulo. Habrá una advertencia sobre el acceso a la reflexión y bien, es justo señalar que sobre dicho acceso “será denegada en una versión futura”. De todos modos, Cómo ocultar advertencia "el acceso ilegal de reflexión" en Java 9 sin argumento JVM? podría ser interesante.
Para Java 8, que había necesidad de cortar en la Lookup
clase para obtener una instancia de consulta apropiada. Esta respuesta muestra una solución, aquí es otro enfoque.