-
Bug
-
Resolution: Unresolved
-
P4
-
8, 11, 17, 21, 24
-
Cause Known
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
Microsoft Windows 10 Version 22H2 (OS Build 19045.5371)
java version "23.0.2" 2025-01-21
Java(TM) SE Runtime Environment (build 23.0.2+7-58)
Java HotSpot(TM) 64-Bit Server VM (build 23.0.2+7-58, mixed mode, sharing)
Also observed with OpenJDK Runtime Environment Temurin-21.0.5+11 (build 21.0.5+11-LTS)
A DESCRIPTION OF THE PROBLEM :
When creating a method handle for a annotation inside of a package visible annotation with a Lookup object that has access to the package, the creation of the MethodHandle succeeds, but calling MethodHandle,invoke fails with an IllegalAccessError.
This happens only when the annotation is "real" annotation uses a target of the invocation; if the interface is implemented by a class it works as expected.
This works as expected with OpenJ9
Developer (liach) note:
When creating a Proxy that has a method that returns objects of package-private types, and that particular method is called and returns non-null, the method throws an `IllegalAccessError`.
The culprit is the checkcast in codeUnwrapValue, which does not perform class or interface resolution when the value is `null`. This has been in place since the initial load of OpenJDK.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the source code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Code runs without exception
ACTUAL -
Exception in thread "main" java.lang.IllegalAccessError: failed to access class Reflection$Y from class jdk.proxy2.$Proxy1 (Reflection$Y is in unnamed module of loader 'app'
; jdk.proxy2.$Proxy1 is in module jdk.proxy2 of loader 'app')
at jdk.proxy2/jdk.proxy2.$Proxy1.value(Unknown Source)
at Reflection.main(Reflection.java:39)
---------- BEGIN SOURCE ----------
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.stream.Stream;
final class Reflection {
@Reflection.Y.Y1({})
private Reflection() {
}
@Retention(RetentionPolicy.RUNTIME)
@interface Y {
String value();
@Retention(RetentionPolicy.RUNTIME)
@interface Y1 {
Y[] value();
}
}
public static void main(String... args) throws Throwable {
MethodHandle methodHandle = MethodHandles.lookup().findVirtual(Reflection.Y.Y1.class, "value", MethodType.methodType(Y[].class));
Reflection.Y.Y1 y1 = Reflection.class.getDeclaredConstructor().getAnnotation(Reflection.Y.Y1.class);
methodHandle.invoke(y1);
}
}
---------- END SOURCE ----------
Microsoft Windows 10 Version 22H2 (OS Build 19045.5371)
java version "23.0.2" 2025-01-21
Java(TM) SE Runtime Environment (build 23.0.2+7-58)
Java HotSpot(TM) 64-Bit Server VM (build 23.0.2+7-58, mixed mode, sharing)
Also observed with OpenJDK Runtime Environment Temurin-21.0.5+11 (build 21.0.5+11-LTS)
A DESCRIPTION OF THE PROBLEM :
When creating a method handle for a annotation inside of a package visible annotation with a Lookup object that has access to the package, the creation of the MethodHandle succeeds, but calling MethodHandle,invoke fails with an IllegalAccessError.
This happens only when the annotation is "real" annotation uses a target of the invocation; if the interface is implemented by a class it works as expected.
This works as expected with OpenJ9
Developer (liach) note:
When creating a Proxy that has a method that returns objects of package-private types, and that particular method is called and returns non-null, the method throws an `IllegalAccessError`.
The culprit is the checkcast in codeUnwrapValue, which does not perform class or interface resolution when the value is `null`. This has been in place since the initial load of OpenJDK.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the source code
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Code runs without exception
ACTUAL -
Exception in thread "main" java.lang.IllegalAccessError: failed to access class Reflection$Y from class jdk.proxy2.$Proxy1 (Reflection$Y is in unnamed module of loader 'app'
; jdk.proxy2.$Proxy1 is in module jdk.proxy2 of loader 'app')
at jdk.proxy2/jdk.proxy2.$Proxy1.value(Unknown Source)
at Reflection.main(Reflection.java:39)
---------- BEGIN SOURCE ----------
import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.stream.Stream;
final class Reflection {
@Reflection.Y.Y1({})
private Reflection() {
}
@Retention(RetentionPolicy.RUNTIME)
@interface Y {
String value();
@Retention(RetentionPolicy.RUNTIME)
@interface Y1 {
Y[] value();
}
}
public static void main(String... args) throws Throwable {
MethodHandle methodHandle = MethodHandles.lookup().findVirtual(Reflection.Y.Y1.class, "value", MethodType.methodType(Y[].class));
Reflection.Y.Y1 y1 = Reflection.class.getDeclaredConstructor().getAnnotation(Reflection.Y.Y1.class);
methodHandle.invoke(y1);
}
}
---------- END SOURCE ----------
- relates to
-
JDK-8333854 IllegalAccessError with proxies after JDK-8332457
-
- Closed
-
- links to
-
Review(master) openjdk/jdk/23567