Jdbi: JDK9 bloqueará setAccessible en módulos

Creado en 21 sept. 2016  ·  22Comentarios  ·  Fuente: jdbi/jdbi

Estamos usando setAccessible(true) para obtener acceso reflexivo a la API privada en un par de lugares. No podemos contar con esto después del lanzamiento de JDK9.

En particular, DefaultMethodHandler en SQL Object está usando setAccessible para obtener acceso a MethodHandle.Lookup para miembros privados, de modo que podamos invocar el método predeterminado ("super").

Ver:

bug

Comentario más útil

Esto debería ser compatible con la próxima versión de Jdbi, probablemente v3.2.0

Todos 22 comentarios

Probé la última instantánea de JDBI en JDK 9-ea + 136 y, desafortunadamente, los métodos predeterminados no funcionan.

java.lang.RuntimeException: java.lang.IllegalAccessException: access to public member failed: org.jdbi.v3.sqlobject.TestSqlObject$Dao.doesTransactionAnnotationWork()boolean/invokeSpecial, from org.jdbi.v3.sqlobject.TestSqlObject$Dao/2 (unnamed module @34b7bfc0)

    at org.jdbi.v3.sqlobject.DefaultMethodHandler.invoke(DefaultMethodHandler.java:63)
    at org.jdbi.v3.sqlobject.TransactionDecorator.lambda$invoke$0(TransactionDecorator.java:54)
    at org.jdbi.v3.core.transaction.LocalTransactionHandler.inTransaction(LocalTransactionHandler.java:173)
    at org.jdbi.v3.core.Handle.inTransaction(Handle.java:478)
    at org.jdbi.v3.sqlobject.TransactionDecorator.invoke(TransactionDecorator.java:57)
    at org.jdbi.v3.sqlobject.SqlObjectFactory.lambda$createInvocationHandler$18(SqlObjectFactory.java:241)
    at com.sun.proxy.$Proxy16.doesTransactionAnnotationWork(Unknown Source)
    at org.jdbi.v3.sqlobject.TestSqlObject.testTransactionAnnotationWorksOnInterfaceDefaultMethod(TestSqlObject.java:115)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(java.base@9-ea/Method.java:535)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base@9-ea/Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base@9-ea/NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@9-ea/DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(java.base@9-ea/Method.java:535)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.IllegalAccessException: access to public member failed: org.jdbi.v3.sqlobject.TestSqlObject$Dao.doesTransactionAnnotationWork()boolean/invokeSpecial, from org.jdbi.v3.sqlobject.TestSqlObject$Dao/2 (unnamed module @34b7bfc0)
    at java.lang.invoke.MemberName.makeAccessException(java.base@9-ea/MemberName.java:915)
    at java.lang.invoke.MethodHandles$Lookup.checkAccess(java.base@9-ea/MethodHandles.java:1924)
    at java.lang.invoke.MethodHandles$Lookup.checkMethod(java.base@9-ea/MethodHandles.java:1864)
    at java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(java.base@9-ea/MethodHandles.java:2013)
    at java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(java.base@9-ea/MethodHandles.java:2007)
    at java.lang.invoke.MethodHandles$Lookup.unreflectSpecial(java.base@9-ea/MethodHandles.java:1539)
    at org.jdbi.v3.sqlobject.DefaultMethodHandler.invoke(DefaultMethodHandler.java:51)
    ... 38 more

Lamentablemente, tampoco veo una solución alternativa para esto.

Es un poco extraño que todas las personas en Internet que experimentan el mismo problema terminen con este truco como única solución. Parece que fue un poco descuidado por parte del equipo de JDK no prestar atención al caso de uso de "métodos predeterminados en proxies".

Hm, lo tengo funcionando con:

Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);
MethodHandles.Lookup lookup = (MethodHandles.Lookup) field.get(null);
Class<?> declaringClass = method.getDeclaringClass();
return lookup.unreflectSpecial(method, declaringClass)
                    .bindTo(target)
                    .invokeWithArguments(args);

No tengo idea de por qué esto funciona con JDK9.

Suspiro. Probablemente deberíamos hacer un seguimiento con los desarrolladores de openjdk sobre esto más temprano que tarde ...

He estado viendo jigsaw-dev durante los últimos días. Ha habido alguna discusión sobre este caso de uso exacto, pero por lo que puedo decir, ha sido más una nota al pie en relación con una discusión furiosa sobre el valor de restringir setAccessible . Parece que mucha gente no está contenta con ese movimiento.

Estoy eliminando esto de los bloqueadores de liberación. No parece probable que aparezca pronto una solución ascendente, y JDK9 aún no se ha lanzado. La eventual solución no debería afectar la API pública.

Me comuniqué con la lista de correo de jigsaw-dev sobre esto. http://jigsaw-dev.1059479.n5.nabble.com/Invoking-default-methods-from-a-Proxy-s-InvocationHandler-in-JDK9-td5714878.html.

Veremos qué sale de ella.

Lo golpeé en core-libs-dev nuevamente.

Esto debería resolverse por nosotros en las compilaciones recientes de JDK9. Al menos en teoría.

Básicamente, cambiaron los controles de seguridad para que cualquiera pueda
unreflectSpecial en un método predeterminado.

Cuando aterrice JDK9, tendremos que cambiar de enfoque dinámicamente dependiendo de
la versión de Java en la que se está ejecutando JDBI.

El 1 de marzo de 2017 a las 2:36 p. M., "Steven Schlansker" [email protected]
escribió:

Lo golpeé en core-libs-dev nuevamente.

-
Recibes esto porque eres el autor del hilo.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/jdbi/jdbi/issues/497#issuecomment-283478025 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AACW5VBktrJYJatnsABFKay_-Ci5WD_Sks5rheTCgaJpZM4KCb6m
.

Ah sí. Desde core-libs-dev:

Puede usar MethodHandles.privateLookupIn (nuevo en JDK 9) para reemplazar el truco de Constructor para obtener un objeto de búsqueda con acceso privado para la clase de destino.
Mandy

¡Es reconfortante escucharlo! Al menos podemos deshacernos de este lío en JDK9.

Hola, he resuelto un problema similar en el PROPIETARIO de mi clase de utilidad, tal vez pueda ayudarlo.

¿Alguna palabra sobre esto? ¿Cuándo podré utilizar JDBI con JDK 9?

Estamos muy interesados ​​en el soporte de Java 9 pero, francamente, todavía no he empezado a investigarlo. La última vez que miré, el ecosistema claramente todavía necesitaba tiempo para asentarse, pero tal vez es hora de darle prioridad a esto.

¿Algo nuevo aquí? JDK 10 está disponible desde hace unos días ...

No hay ningún cambio obvio en jdk9, es mejor ir directamente a 10

Parece que es posible que tengamos que ramificar el código y usar la reflexión para aprovechar los nuevos métodos agregados en JDK9 sin romper la compatibilidad con 8. La forma más rápida de avanzar aquí es enviar un parche o al menos un poco de trabajo preliminar para determinar el cambio mínimo necesario :) de lo contrario intentaré echarle un vistazo a esto en algún momento de esta semana.

Y con suerte, la mayor parte del trabajo para llegar a 10 será en realidad para llegar a 9; no creo que haya grandes cambios en 10 que esperamos que rompan cosas, mientras que ciertamente sabemos que 9 rompieron cosas ...

Tengo una rama en esto que no necesita una construcción dual, pero primero necesita una solución

De acuerdo, no empezaré a hackearlo entonces.

Esto debería ser compatible con la próxima versión de Jdbi, probablemente v3.2.0

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

jimmyhmiller picture jimmyhmiller  ·  6Comentarios

kkrgwbj picture kkrgwbj  ·  4Comentarios

rherrmann picture rherrmann  ·  4Comentarios

mcarabolante picture mcarabolante  ·  4Comentarios

buremba picture buremba  ·  5Comentarios