Jdbi: JDK9 akan memblokir setAccessible pada modul

Dibuat pada 21 Sep 2016  ·  22Komentar  ·  Sumber: jdbi/jdbi

Kami menggunakan setAccessible(true) untuk mendapatkan akses reflektif ke API pribadi di beberapa tempat. Kami tidak dapat mengandalkan ini setelah JDK9 dirilis.

Secara khusus, DefaultMethodHandler di SQL Object menggunakan setAccessible untuk mendapatkan akses ke MethodHandle.Lookup untuk anggota pribadi, sehingga kita dapat memanggil metode default ("super").

Lihat:

bug

Komentar yang paling membantu

Ini harus didukung dalam rilis Jdbi berikutnya--mungkin v3.2.0

Semua 22 komentar

Saya telah menguji snapshot JDBI terbaru pada JDK 9-ea+136 dan, sayangnya, metode default tidak berfungsi.

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

Sayangnya, saya juga tidak melihat solusi untuk ini.

Agak aneh semua orang di Internet yang mengalami masalah yang sama, berakhir dengan peretasan ini sebagai satu-satunya solusi. Sepertinya ada sedikit kelalaian dari tim JDK untuk tidak memperhatikan kasus penggunaan "metode default dalam proxy".

Hm, membuatnya bekerja dengan:

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

Tidak tahu mengapa ini bekerja dengan JDK9.

Mendesah. Kami mungkin harus menindaklanjuti dengan pengembang openjdk tentang ini lebih cepat daripada nanti ...

Saya telah menonton jigsaw-dev selama beberapa hari terakhir. Ada beberapa diskusi tentang kasus penggunaan yang tepat ini, tetapi dari apa yang saya tahu ini lebih merupakan catatan kaki relatif terhadap diskusi yang mengamuk tentang nilai membatasi setAccessible . Sepertinya banyak orang tidak senang dengan langkah itu.

Saya menghapus ini dari pemblokir rilis. Perbaikan upstream sepertinya tidak akan segera muncul, dan JDK9 belum dirilis. Perbaikan akhirnya tidak akan memengaruhi API publik.

Saya menghubungi milis jigsaw-dev tentang hal ini. http://jigsaw-dev.1059479.n5.nabble.com/Invoking-default-methods-from-a-Proxy-s-InvocationHandler-in-JDK9-td5714878.html.

Kita lihat apa yang keluar darinya.

Menabraknya di core-libs-dev lagi.

Ini harus diselesaikan untuk kami di build JDK9 baru-baru ini. Setidaknya secara teori.

Pada dasarnya, mereka mengubah pemeriksaan keamanan sehingga siapa pun dapat
unreflectSpecial pada metode default.

Saat JDK9 mendarat, kita harus beralih pendekatan secara dinamis tergantung pada
versi Java yang dijalankan JDBI.

Pada 1 Mar 2017 14:36, "Steven Schlansker" [email protected]
menulis:

Menabraknya di core-libs-dev lagi.


Anda menerima ini karena Anda yang menulis utas.
Balas email ini secara langsung, lihat di GitHub
https://github.com/jdbi/jdbi/issues/497#issuecomment-283478025 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/AACW5VBktrJYJatnsABFKay_-Ci5WD_Sks5rheTCgaJpZM4KCb6m
.

Ah, ya. Dari core-libs-dev:

Anda dapat menggunakan MethodHandles.privateLookupIn (baru di JDK 9) untuk menggantikan konstruktor hack untuk mendapatkan objek Lookup dengan akses pribadi untuk kelas target.
Mandy

Itu menyegarkan untuk didengar! Setidaknya kita bisa menyingkirkan kekacauan ini di JDK9.

Hai Saya telah memecahkan masalah serupa pada PEMILIK proyek saya yang memanggil metode default pada antarmuka menggunakan JDK9, silakan lihat kelas utilitas saya mungkin dapat membantu Anda.

Ada kata tentang ini? Kapan saya dapat menggunakan JDBI dengan JDK 9?

Kami sangat tertarik dengan dukungan Java 9 tetapi terus terang saya belum mulai menyelidikinya. Terakhir saya lihat ekosistemnya jelas masih butuh waktu untuk menetap, tapi mungkin ini saatnya untuk mendobrak prioritas ini.

Ada yang baru di sini? JDK 10 sudah keluar sejak beberapa hari...

Tidak ada perubahan yang jelas di jdk9, lebih baik langsung ke 10

Sepertinya kita mungkin harus membuat cabang kode dan menggunakan refleksi untuk memanfaatkan metode baru yang ditambahkan di JDK9 tanpa merusak kompatibilitas untuk 8. Cara tercepat untuk maju di sini adalah dengan mengirimkan tambalan atau setidaknya beberapa kerja keras untuk mencari tahu perubahan minimum perlu :) jika tidak, saya akan mencoba melihatnya pada minggu ini.

Dan mudah-mudahan sebagian besar pekerjaan untuk mencapai 10 akan benar-benar dalam mencapai 9 -- Saya tidak berpikir ada perubahan besar dalam 10 yang kita harapkan untuk memecahkan sesuatu, sedangkan kita tentu tahu 9 hal yang rusak...

Saya memiliki cabang ini yang tidak memerlukan build ganda, tetapi perlu diperbaiki terlebih dahulu

OK saya tidak akan mulai meretasnya.

Ini harus didukung dalam rilis Jdbi berikutnya--mungkin v3.2.0

Apakah halaman ini membantu?
0 / 5 - 0 peringkat