Jdbi: JDK9 bloquera setAccessible sur les modules

Créé le 21 sept. 2016  ·  22Commentaires  ·  Source: jdbi/jdbi

Nous utilisons setAccessible(true) pour obtenir un accès réfléchissant à l'API privée à quelques endroits. Nous ne pouvons pas compter là-dessus après la sortie de JDK9.

En particulier, DefaultMethodHandler dans SQL Object utilise setAccessible pour accéder aux MethodHandle.Lookup pour les membres privés, afin que nous puissions invoquer la méthode par défaut ("super").

Voir:

bug

Commentaire le plus utile

Cela devrait être pris en charge dans la prochaine version de Jdbi - probablement v3.2.0

Tous les 22 commentaires

J'ai testé le dernier instantané JDBI sur JDK 9-ea+136 et, malheureusement, les méthodes par défaut ne fonctionnent pas.

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

Malheureusement, je ne vois pas non plus de solution de contournement pour cela.

C'est un peu étrange que toutes les personnes sur Internet qui rencontrent le même problème se retrouvent avec ce hack comme seule solution. Il semble que l'équipe JDK ait un peu oublié de ne pas prêter attention au cas d'utilisation des "méthodes par défaut dans les proxys".

Hm, ça marche avec :

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

Aucune idée de pourquoi cela fonctionne avec JDK9.

Soupir. Nous devrions probablement faire un suivi avec les développeurs d'openjdk à ce sujet le plus tôt possible ...

J'ai regardé jigsaw-dev ces derniers jours. Il y a eu des discussions sur ce cas d'utilisation exact, mais d'après ce que je peux dire, il s'agit plutôt d'une note de bas de page relative à une discussion qui fait rage sur la valeur de la restriction de setAccessible . On dirait que beaucoup de gens ne sont pas contents de cette décision.

Je supprime cela des bloqueurs de version. Un correctif en amont ne semble pas susceptible d'apparaître bientôt, et JDK9 n'est pas encore publié. Le correctif éventuel ne devrait pas affecter l'API publique.

J'ai contacté la liste de diffusion jigsaw-dev à ce sujet. http://jigsaw-dev.1059479.n5.nabble.com/Invoking-default-methods-from-a-Proxy-s-InvocationHandler-in-JDK9-td5714878.html.

On verra ce qu'il en sortira.

Je l'ai à nouveau repoussé sur core-libs-dev.

Cela devrait être résolu pour nous dans les versions récentes de JDK9. Du moins en théorie.

Fondamentalement, ils ont modifié les contrôles de sécurité afin que tout le monde puisse
unreflectSpecial sur une méthode par défaut.

Lorsque JDK9 atterrira, nous devrons changer d'approche dynamiquement en fonction de
la version Java JDBI s'exécute.

Le 1er mars 2017 14:36, notifications "Steven Schlansker"@github.com
a écrit:

Je l'ai à nouveau repoussé sur core-libs-dev.

-
Vous recevez ceci parce que vous avez créé le fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/jdbi/jdbi/issues/497#issuecomment-283478025 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AACW5VBktrJYJatnsABFKay_-Ci5WD_Sks5rheTCgaJpZM4KCb6m
.

Ah ouais. De core-libs-dev :

Vous pouvez utiliser MethodHandles.privateLookupIn (nouveau dans JDK 9) pour remplacer le hack Constructor afin d'obtenir un objet Lookup avec un accès privé pour la classe cible.
Mandy

C'est rafraîchissant à entendre ! Au moins, nous pouvons nous débarrasser de ce gâchis dans JDK9.

Salut, j'ai résolu un problème similaire sur mon projet OWNER qui appelle des méthodes par défaut sur les interfaces utilisant JDK9, veuillez jeter un œil à ma classe utilitaire peut

Un mot à ce sujet ? Quand pourrai-je utiliser JDBI avec JDK 9 ?

Nous sommes très intéressés par le support de Java 9 mais franchement je n'ai pas encore commencé à m'y intéresser. La dernière fois que j'ai regardé, l'écosystème avait clairement encore besoin de temps pour s'installer, mais il est peut-être temps de passer à la priorité.

Rien de nouveau ici ? JDK 10 est sorti depuis quelques jours...

Il n'y a pas de changement évident dans jdk9, il vaut mieux passer directement à 10

Il semble que nous devions peut-être brancher le code et utiliser la réflexion pour tirer parti des nouvelles méthodes ajoutées dans JDK9 sans rompre la compatibilité pour 8. Le moyen le plus rapide ici est de soumettre un correctif ou au moins quelques démarches pour déterminer le changement minimum nécessaire :) sinon je vais essayer d'y jeter un œil cette semaine.

Et j'espère que la majorité du travail pour arriver à 10 sera en fait d'arriver à 9 -- je ne pense pas qu'il y ait de grands changements dans 10, nous nous attendons à casser des choses, alors que nous savons certainement que 9 choses ont cassé …

J'ai une branche là-dessus qui n'a pas besoin d'une double construction, mais elle a d'abord besoin d'un correctif

OK, je ne vais pas commencer à hacker dessus alors.

Cela devrait être pris en charge dans la prochaine version de Jdbi - probablement v3.2.0

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

nonameplum picture nonameplum  ·  5Commentaires

dhardtke picture dhardtke  ·  3Commentaires

jimmyhmiller picture jimmyhmiller  ·  6Commentaires

buremba picture buremba  ·  5Commentaires

stevenschlansker picture stevenschlansker  ·  4Commentaires