In a static method (Annotated with @CallerSensitive
) I try to get the name of the calling class:
@CallerSensitive
public static void someMethod() {
String name = sun.reflect.Reflection.getCallerClass().getName();
...
}
I get the error:
java.lang.InternalError: CallerSensitive annotation expected at frame 1
What is wrong here?
References
UPDATE
I am using java 8 (u25) and the method getCallerClass()
is not deprecated (getCallerClass(int)
is deprecated) as can be seen when disassembling the bytecode:
$ /usr/lib/jvm/java-8-oracle/bin/javap -cp /usr/lib/jvm/java-8-oracle/jre/lib/rt.jar -verbose sun.reflect.Reflection > bytecode
Output (only relevant lines are shown)
Classfile jar:file:/usr/lib/jvm/jdk1.8.0_25/jre/lib/rt.jar!/sun/reflect/Reflection.class
Last modified Sep 17, 2014; size 6476 bytes
Compiled from "Reflection.java"
public class sun.reflect.Reflection
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#78 = Utf8 Lsun/reflect/CallerSensitive;
#80 = Utf8 Deprecated
#82 = Utf8 Ljava/lang/Deprecated;
{
public sun.reflect.Reflection();
descriptor: ()V
flags: ACC_PUBLIC
public static native java.lang.Class<?> getCallerClass();
descriptor: ()Ljava/lang/Class;
flags: ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
Signature: #76 // ()Ljava/lang/Class<*>;
RuntimeVisibleAnnotations:
0: #78()
public static native java.lang.Class<?> getCallerClass(int);
descriptor: (I)Ljava/lang/Class;
flags: ACC_PUBLIC, ACC_STATIC, ACC_NATIVE
Deprecated: true
Signature: #81 // (I)Ljava/lang/Class<*>;
RuntimeVisibleAnnotations:
0: #82()
Only privileged code can use this annotation. the code is privileged if it is loaded via bootstrap class loader or extension class loader.
excerpt from Open JDK source file classFileParser.cpp
// Privileged code can use all annotations. Other code silently drops some.
const bool privileged = loader_data->is_the_null_class_loader_data() ||
loader_data->is_ext_class_loader_data() ||
loader_data->is_anonymous();
To make java load your classes via bootstrap class loader you can use the -Xbootclasspath/a
option to add your classes to the bootstrap class path when running java
:
java -Xbootclasspath/a:classes_dir_or_jar_file fully.qualified.mainClassName
To have your classes loaded via extension class loader instead, you need to put your jar file in $JAVA_HOME/jre/lib/ext
directory or any other directories set in java.ext.dirs
system property.
getCallerClass()
is removed from Java8. When I run this example in Java 8, I get the same error. Running with Java 7 (1.7.0_55) I get the name of the calling class. Anyway I would refrain from using anything directly from the sun.* package hierarchy.
To get the name of the calling class you can do the following (I just used the instance initializer to get the name, you should derive from SecurityManager and provide a getCallerClass() method in your class):
public static void someMethod() {
new SecurityManager() {
{
String name = getClassContext()[1].getSimpleName();
System.err.println(name == null ? "null" : name);
}
};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With