Jdbi: JDK9 blockiert setAccessible auf Modulen

Erstellt am 21. Sept. 2016  Â·  22Kommentare  Â·  Quelle: jdbi/jdbi

Wir verwenden setAccessible(true) , um an einigen Stellen reflektierenden Zugriff auf die private API zu erhalten. Darauf können wir uns nach der Veröffentlichung von JDK9 nicht verlassen.

Insbesondere DefaultMethodHandler in SQL Object verwendet setAccessible , um Zugriff auf MethodHandle.Lookup fĂŒr private Mitglieder zu erhalten, damit wir die Standardmethode ("super") aufrufen können.

Sehen:

bug

Hilfreichster Kommentar

Dies sollte in der nĂ€chsten Jdbi-Version unterstĂŒtzt werden – wahrscheinlich v3.2.0

Alle 22 Kommentare

Ich habe den neuesten JDBI-Snapshot auf JDK 9-ea+136 getestet und leider funktionieren die Standardmethoden nicht.

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

Leider sehe ich dafĂŒr auch keinen Workaround.

Das ist irgendwie seltsam, dass alle Leute im Internet, die das gleiche Problem haben, mit diesem Hack als einziger Lösung enden. Es sieht so aus, als ob es vom JDK-Team ein wenig versÀumt wurde, den Anwendungsfall "Standardmethoden in Proxys" nicht zu beachten.

Hm, habe es funktioniert mit:

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

Keine Ahnung warum das mit JDK9 funktioniert.

Seufzen. Wir sollten uns wahrscheinlich frĂŒher oder spĂ€ter mit den openjdk-Entwicklern in Verbindung setzen...

Ich habe Jigsaw-dev in den letzten Tagen beobachtet. Es gab einige Diskussionen ĂŒber diesen genauen Anwendungsfall, aber soweit ich das beurteilen kann, war es eher eine Fußnote im Vergleich zu einer wĂŒtenden Diskussion ĂŒber den Wert der BeschrĂ€nkung von setAccessible . Es scheint, als ob viele Leute ĂŒber diesen Schritt nicht glĂŒcklich sind.

Ich entferne dies von Releaseblockern. Ein Upstream-Fix wird wahrscheinlich nicht bald erscheinen, und JDK9 ist noch nicht veröffentlicht. Der eventuelle Fix sollte sich nicht auf die öffentliche API auswirken.

Ich habe die Mailingliste jigsaw-dev diesbezĂŒglich kontaktiert. http://jigsaw-dev.1059479.n5.nabble.com/Invoking-default-methods-from-a-Proxy-s-InvocationHandler-in-JDK9-td5714878.html.

Wir werden sehen, was dabei herauskommt.

Habe es wieder auf core-libs-dev gestoßen.

Dies sollte fĂŒr uns in den letzten JDK9-Builds behoben sein. Zumindest theoretisch.

Im Grunde haben sie die Sicherheitskontrollen so geÀndert, dass jeder es kann
unreflectSpecial fĂŒr eine Standardmethode.

Wenn JDK9 landet, mĂŒssen wir die AnsĂ€tze dynamisch wechseln, je nachdem
die Java-Version JDBI lÀuft.

Am 1. MĂ€rz 2017, 14:36 ​​Uhr, "Steven Schlansker" [email protected]
schrieb:

Habe es wieder auf core-libs-dev gestoßen.

—
Sie erhalten dies, weil Sie den Thread verfasst haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/jdbi/jdbi/issues/497#issuecomment-283478025 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AACW5VBktrJYJatnsABFKay_-Ci5WD_Sks5rheTCgaJpZM4KCb6m
.

Oh ja. Von core-libs-dev:

Sie können MethodHandles.privateLookupIn (neu in JDK 9) verwenden, um den Constructor-Hack zu ersetzen, um ein Lookup-Objekt mit privatem Zugriff fĂŒr die Zielklasse zu erhalten.
Mandy

Das ist erfrischend zu hören! Zumindest können wir dieses Durcheinander in JDK9 beseitigen.

Hallo, ich habe ein Àhnliches Problem in meinem Projekt OWNER gelöst, das Standardmethoden auf Schnittstellen mit JDK9 aufruft. Bitte werfen Sie einen Blick auf meine Dienstprogrammklasse, vielleicht kann sie Ihnen helfen.

Irgendein Wort dazu? Wann kann ich JDBI mit JDK 9 verwenden?

Wir sind sehr an der UnterstĂŒtzung von Java 9 interessiert, aber ehrlich gesagt habe ich mich noch nicht damit befasst. Zuletzt habe ich nachgesehen, dass das Ökosystem eindeutig noch Zeit braucht, um sich zu beruhigen, aber vielleicht ist es an der Zeit, die PrioritĂ€t zu erhöhen.

Gibt es hier etwas Neues? JDK 10 ist seit ein paar Tagen draußen...

Es gibt keine offensichtliche Änderung in jdk9, es ist besser, direkt zu 10 . zu gehen

Es hört sich so an, als mĂŒssten wir den Code verzweigen und Reflektion verwenden, um die neuen Methoden zu nutzen, die in JDK9 hinzugefĂŒgt wurden, ohne die KompatibilitĂ€t fĂŒr 8 zu beeintrĂ€chtigen. Der schnellste Weg hier ist, einen Patch einzureichen oder zumindest einige Kleinarbeit zu leisten, um die minimale Änderung herauszufinden notwendig :) ansonsten werde ich mir das mal diese woche mal anschauen.

Und hoffentlich wird der Großteil der Arbeit, um 10 zu erreichen, tatsĂ€chlich darin bestehen, 9 zu erreichen – ich glaube nicht, dass es bei 10 große VerĂ€nderungen gibt, von denen wir erwarten, dass sie Dinge kaputt machen, wĂ€hrend wir sicherlich wissen, dass 9 Dinge kaputt machen ...

Ich habe einen Branch dazu, der keinen Dual-Build benötigt, aber zuerst muss er repariert werden

OK, dann werde ich nicht anfangen, darauf zu hacken.

Dies sollte in der nĂ€chsten Jdbi-Version unterstĂŒtzt werden – wahrscheinlich v3.2.0

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen