由于 IllegalAccessException,Clojure 无法在 java 11 上调用接口默认方法
Clojure fails to call an interface default method on java 11 due to IllegalAccessException
我已将我的 Clojure 应用程序从 jdk8 移动到 jdk11 (Zulu JRE 11),它开始无法在接口上调用 default method,该接口的实现是机器生成的(看起来像 #object[com.sun.proxy.$Proxy110 0x28466aa5 nil]
).
我愿意
(.someDefaultMethod iinterface-impl)
并获得
java.lang.IllegalAccessException: access to public member failed:
my.IInterface.someDefaultMethod[Ljava.lang.Object;@172aedbe/invokeSpecial, from my.IInterface/2 (unnamed module @627551fb)
at java.base/java.lang.invoke.MemberName.makeAccessException(MemberName.java:942)
at java.base/java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:2206)
at java.base/java.lang.invoke.MethodHandles$Lookup.checkMethod(MethodHandles.java:2146)
at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:2290)
at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:2283)
at java.base/java.lang.invoke.MethodHandles$Lookup.unreflectSpecial(MethodHandles.java:1798)
at my.SomeService.invoke(SomeService.java:305)
有什么解决办法吗?谢谢!
事实证明错误不是由于 Clojure 引起的,而是由于在代理处理程序的 invoke
:
中调用默认方法的编码方式引起的
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Proxy: calling " + method);
// Default methods are public non-abstract instance methods
// declared in an interface.
if (((method.getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) ==
Modifier.PUBLIC) && method.getDeclaringClass().isInterface()) {
// see https://rmannibucau.wordpress.com/2014/03/27/java-8-default-interface-methods-and-jdk-dynamic-proxies/
final Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
final Class<?> declaringClass = method.getDeclaringClass();
return constructor.newInstance(declaringClass, MethodHandles.Lookup.PRIVATE)
.unreflectSpecial(method, declaringClass)
.bindTo(proxy)
.invokeWithArguments(args);
}
return null;
}
我已将我的 Clojure 应用程序从 jdk8 移动到 jdk11 (Zulu JRE 11),它开始无法在接口上调用 default method,该接口的实现是机器生成的(看起来像 #object[com.sun.proxy.$Proxy110 0x28466aa5 nil]
).
我愿意
(.someDefaultMethod iinterface-impl)
并获得
java.lang.IllegalAccessException: access to public member failed:
my.IInterface.someDefaultMethod[Ljava.lang.Object;@172aedbe/invokeSpecial, from my.IInterface/2 (unnamed module @627551fb)
at java.base/java.lang.invoke.MemberName.makeAccessException(MemberName.java:942)
at java.base/java.lang.invoke.MethodHandles$Lookup.checkAccess(MethodHandles.java:2206)
at java.base/java.lang.invoke.MethodHandles$Lookup.checkMethod(MethodHandles.java:2146)
at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodCommon(MethodHandles.java:2290)
at java.base/java.lang.invoke.MethodHandles$Lookup.getDirectMethodNoSecurityManager(MethodHandles.java:2283)
at java.base/java.lang.invoke.MethodHandles$Lookup.unreflectSpecial(MethodHandles.java:1798)
at my.SomeService.invoke(SomeService.java:305)
有什么解决办法吗?谢谢!
事实证明错误不是由于 Clojure 引起的,而是由于在代理处理程序的 invoke
:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Proxy: calling " + method);
// Default methods are public non-abstract instance methods
// declared in an interface.
if (((method.getModifiers() & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC)) ==
Modifier.PUBLIC) && method.getDeclaringClass().isInterface()) {
// see https://rmannibucau.wordpress.com/2014/03/27/java-8-default-interface-methods-and-jdk-dynamic-proxies/
final Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
if (!constructor.isAccessible()) {
constructor.setAccessible(true);
}
final Class<?> declaringClass = method.getDeclaringClass();
return constructor.newInstance(declaringClass, MethodHandles.Lookup.PRIVATE)
.unreflectSpecial(method, declaringClass)
.bindTo(proxy)
.invokeWithArguments(args);
}
return null;
}