Jdbi: JDK9λŠ” λͺ¨λ“ˆμ—μ„œ setAccessible을 μ°¨λ‹¨ν•©λ‹ˆλ‹€.

에 λ§Œλ“  2016λ…„ 09μ›” 21일  Β·  22μ½”λ©˜νŠΈ  Β·  좜처: jdbi/jdbi

μš°λ¦¬λŠ” setAccessible(true) λ₯Ό μ‚¬μš©ν•˜μ—¬ λͺ‡ κ³³μ—μ„œ λΉ„κ³΅κ°œ API에 λŒ€ν•œ λ°˜μ‚¬ μ•‘μ„ΈμŠ€λ₯Ό μ–»κ³  μžˆμŠ΅λ‹ˆλ‹€. JDK9κ°€ μΆœμ‹œλœ ν›„μ—λŠ” 이λ₯Ό κΈ°λŒ€ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

특히 SQL Object의 DefaultMethodHandler λŠ” setAccessible λ₯Ό μ‚¬μš©ν•˜μ—¬ private λ©€λ²„μ˜ MethodHandle.Lookup 에 μ•‘μ„ΈμŠ€ν•˜λ―€λ‘œ κΈ°λ³Έ("수퍼") λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€.

보닀:

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

이것은 λ‹€μŒ Jdbi 릴리슀(μ•„λ§ˆλ„ v3.2.0)μ—μ„œ μ§€μ›λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

λͺ¨λ“  22 λŒ“κΈ€

JDK 9-ea+136μ—μ„œ μ΅œμ‹  JDBI μŠ€λƒ…μƒ·μ„ ν…ŒμŠ€νŠΈν–ˆλŠ”λ° λΆˆν–‰νžˆλ„ κΈ°λ³Έ 방법이 μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

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

μŠ¬ν”„κ²Œλ„ λ‚˜λŠ” 이것에 λŒ€ν•œ ν•΄κ²° 방법을 보지 λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.

μΈν„°λ„·μ—μ„œ 같은 문제λ₯Ό κ²½ν—˜ν•˜λŠ” λͺ¨λ“  μ‚¬λžŒλ“€μ΄ 이 해킹을 μœ μΌν•œ ν•΄κ²°μ±…μœΌλ‘œ μ‚ΌλŠ”λ‹€λŠ” 것은 μ΄μƒν•œ μΌμž…λ‹ˆλ‹€. "ν”„λ‘μ‹œμ˜ κΈ°λ³Έ 방법" μ‚¬μš© 사둀에 주의λ₯Ό κΈ°μšΈμ΄μ§€ μ•Šμ€ 것은 JDK νŒ€μ˜ μ•½κ°„μ˜ κ°λ…μ΄μ—ˆλ˜ 것 κ°™μŠ΅λ‹ˆλ‹€.

흠, λ‹€μŒκ³Ό 같이 μž‘λ™ν•©λ‹ˆλ‹€.

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

이것이 JDK9μ—μ„œ μž‘λ™ν•˜λŠ” 이유λ₯Ό λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€.

ν•œμˆ¨μ„ 쉬닀. μš°λ¦¬λŠ” μ•„λ§ˆλ„ 이것에 λŒ€ν•΄ λ‚˜μ€‘μ— openjdk κ°œλ°œμžμ—κ²Œ 후속 쑰치λ₯Ό μ·¨ν•΄μ•Ό ν•  κ²ƒμž…λ‹ˆλ‹€...

λ‚˜λŠ” μ§€λ‚œ λ©°μΉ  λ™μ•ˆ jigsaw-devλ₯Όλ³΄κ³ μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 이 μ •ν™•ν•œ μ‚¬μš© 사둀에 λŒ€ν•œ λͺ‡ 가지 λ…Όμ˜κ°€ μžˆμ—ˆμ§€λ§Œ setAccessible μ œν•œμ˜ κ°€μΉ˜μ— λŒ€ν•œ κ²©λ ¬ν•œ ν† λ‘ κ³Ό κ΄€λ ¨λœ 각주에 더 가깝닀고 말할 수 μžˆμŠ΅λ‹ˆλ‹€. λ§Žμ€ μ‚¬λžŒλ“€μ΄ κ·Έ μ›€μ§μž„μ— λ§Œμ‘±ν•˜μ§€ λͺ»ν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

릴리슀 μ°¨λ‹¨κΈ°μ—μ„œ 이것을 μ œκ±°ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ—…μŠ€νŠΈλ¦Ό μˆ˜μ • 사항이 곧 λ‚˜νƒ€λ‚˜μ§€ μ•Šμ„ κ²ƒμœΌλ‘œ 보이며 JDK9λŠ” 아직 λ¦΄λ¦¬μŠ€λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. μ΅œμ’… μˆ˜μ • 사항은 곡개 API에 영ν–₯을 λ―ΈμΉ˜μ§€ μ•Šμ•„μ•Ό ν•©λ‹ˆλ‹€.

이에 λŒ€ν•΄ jigsaw-dev 메일링 λ¦¬μŠ€νŠΈμ— μ—°λ½ν–ˆμŠ΅λ‹ˆλ‹€. http://jigsaw-dev.1059479.n5.nabble.com/Invoking-default-methods-from-a-Proxy-s-InvocationHandler-in-JDK9-td5714878.html.

μš°λ¦¬λŠ” κ·Έκ²ƒμ—μ„œ 무엇이 λ‚˜μ˜€λŠ”μ§€ λ³Ό κ²ƒμž…λ‹ˆλ‹€.

core-lib-dev에 λ‹€μ‹œ λΆ€λ”ͺμ³€μŠ΅λ‹ˆλ‹€.

이것은 졜근 JDK9 λΉŒλ“œμ—μ„œ ν•΄κ²°λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. 적어도 μ΄λ‘ μƒμœΌλ‘œλŠ”.

기본적으둜 λ³΄μ•ˆ 검사λ₯Ό λ³€κ²½ν•˜μ—¬ λˆ„κ΅¬λ‚˜
κΈ°λ³Έ λ©”μ†Œλ“œμ— λŒ€ν•œ unreflectSpecial.

JDK9κ°€ μΆœμ‹œλ˜λ©΄ λ‹€μŒμ— 따라 μ ‘κ·Ό 방식을 λ™μ μœΌλ‘œ μ „ν™˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.
Java 버전 JDBIκ°€ μ‹€ν–‰ μ€‘μž…λ‹ˆλ‹€.

2017λ…„ 3μ›” 1일 μ˜€ν›„ 2μ‹œ 36λΆ„, "Steven Schlansker" [email protected]
썼닀:

core-lib-dev에 λ‹€μ‹œ λΆ€λ”ͺμ³€μŠ΅λ‹ˆλ‹€.

β€”
μŠ€λ ˆλ“œλ₯Ό μž‘μ„±ν–ˆκΈ° λ•Œλ¬Έμ— 이 λ©”μ‹œμ§€λ₯Ό λ°›λŠ” κ²ƒμž…λ‹ˆλ‹€.
이 이메일에 직접 λ‹΅μž₯ν•˜κ³  GitHubμ—μ„œ 확인
https://github.com/jdbi/jdbi/issues/497#issuecomment-283478025 λ˜λŠ” μŒμ†Œκ±°
μŠ€λ ˆλ“œ
https://github.com/notifications/unsubscribe-auth/AACW5VBktrJYJatnsABFKay_-Ci5WD_Sks5rheTCgaJpZM4KCb6m
.

μ•„, 그래. core-libs-devμ—μ„œ:

MethodHandles.privateLookupIn(JDK 9의 μƒˆλ‘œμš΄ κΈ°λŠ₯)을 μ‚¬μš©ν•˜μ—¬ μƒμ„±μž 해킹을 λŒ€μ²΄ν•˜μ—¬ λŒ€μƒ ν΄λž˜μŠ€μ— λŒ€ν•œ λΉ„κ³΅κ°œ μ•‘μ„ΈμŠ€λ‘œ 쑰회 개체λ₯Ό κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.
맨디

λ“£κΈ°λ§Œ 해도 μƒμΎŒν•©λ‹ˆλ‹€! μ΅œμ†Œν•œ JDK9μ—μ„œλŠ” 이 ν˜Όλž€μ„ 없앨 수 μžˆμŠ΅λ‹ˆλ‹€.

μ•ˆλ…•ν•˜μ„Έμš” JDK9λ₯Ό μ‚¬μš©ν•˜μ—¬ μΈν„°νŽ˜μ΄μŠ€μ—μ„œ κΈ°λ³Έ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ” ν”„λ‘œμ νŠΈ μ†Œμœ μž μ—μ„œ μœ μ‚¬ν•œ 문제λ₯Ό ν•΄κ²°ν–ˆμŠ΅λ‹ˆλ‹€. 제 μœ ν‹Έλ¦¬ν‹° 클래슀λ₯Ό μ‚΄νŽ΄λ³΄μ‹­μ‹œμ˜€. 도움이 될 수 μžˆμŠ΅λ‹ˆλ‹€.

이것에 λŒ€ν•œ μ–΄λ–€ 말? μ–Έμ œ JDBIλ₯Ό JDK 9와 ν•¨κ»˜ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆκΉŒ?

μš°λ¦¬λŠ” Java 9 지원에 맀우 관심이 μžˆμ§€λ§Œ μ†”μ§νžˆ 아직 쑰사λ₯Ό μ‹œμž‘ν•˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€. λ§ˆμ§€λ§‰μœΌλ‘œ μƒνƒœκ³„κ°€ 아직 μ •μ°©ν•  μ‹œκ°„μ΄ ν•„μš”ν•˜λ‹€λŠ” 것을 λΆ„λͺ…νžˆ λ³΄μ•˜μ§€λ§Œ, μ•„λ§ˆλ„ μ΄κ²ƒμ˜ μš°μ„  μˆœμœ„λ₯Ό λΆ€λ”ͺ힐 λ•ŒμΌ κ²ƒμž…λ‹ˆλ‹€.

여기에 μƒˆλ‘œμš΄ 것이 μžˆμŠ΅λ‹ˆκΉŒ? JDK 10이 λ©°μΉ  λ§Œμ— μ—†μ–΄μ‘ŒμŠ΅λ‹ˆλ‹€ ...

jdk9μ—λŠ” λˆˆμ— λ„λŠ” λ³€ν™”κ°€ μ—†μŠ΅λ‹ˆλ‹€. 10으둜 λ°”λ‘œ μ΄λ™ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

μ½”λ“œλ₯Ό λΆ„κΈ°ν•˜κ³  λ¦¬ν”Œλ ‰μ…˜μ„ μ‚¬μš©ν•˜μ—¬ 8과의 ν˜Έν™˜μ„±μ„ μ†μƒμ‹œν‚€μ§€ μ•Šκ³  JDK9에 μΆ”κ°€λœ μƒˆλ‘œμš΄ 방법을 ν™œμš©ν•΄μ•Ό ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ—¬κΈ°μ„œ μ•žμœΌλ‘œ λ‚˜μ•„κ°€λŠ” κ°€μž₯ λΉ λ₯Έ 방법은 패치λ₯Ό μ œμΆœν•˜κ±°λ‚˜ μ΅œμ†Œν•œμ˜ λ³€κ²½ 사항을 νŒŒμ•…ν•˜κΈ° μœ„ν•œ μ•½κ°„μ˜ λ…Έλ ₯을 κΈ°μšΈμ΄λŠ” κ²ƒμž…λ‹ˆλ‹€. ν•„μš”ν•©λ‹ˆλ‹€ :) 그렇지 μ•ŠμœΌλ©΄ 이번 주에 이것을 μ‚΄νŽ΄λ³΄λ €κ³  ν•©λ‹ˆλ‹€.

그리고 λ°”λΌκ±΄λŒ€ 10에 λ„λ‹¬ν•˜λŠ” μž‘μ—…μ˜ λŒ€λΆ€λΆ„μ€ μ‹€μ œλ‘œ 9에 λ„λ‹¬ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 10에 큰 λ³€ν™”κ°€ μ—†λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€. μš°λ¦¬κ°€ 깨뜨릴 κ²ƒμœΌλ‘œ μ˜ˆμƒν•˜λŠ” λ°˜λ©΄μ— 9λŠ” ν™•μ‹€νžˆ κΉ¨μ‘ŒμŠ΅λ‹ˆλ‹€...

이쀑 λΉŒλ“œκ°€ ν•„μš”ν•˜μ§€ μ•Šμ€ λΆ„κΈ°κ°€ μžˆμ§€λ§Œ λ¨Όμ € μˆ˜μ •ν•΄μ•Ό ν•©λ‹ˆλ‹€.

μ•Œκ² μŠ΅λ‹ˆλ‹€. 그러면 해킹을 μ‹œμž‘ν•˜μ§€ μ•Šκ² μŠ΅λ‹ˆλ‹€.

이것은 λ‹€μŒ Jdbi 릴리슀(μ•„λ§ˆλ„ v3.2.0)μ—μ„œ μ§€μ›λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰