Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.InternalError: CallerSensitive annotation expected at frame 1

Tags:

java

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

  • http://www.infoq.com/news/2013/07/Oracle-Removes-getCallerClass
  • http://openjdk.java.net/jeps/176

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()
like image 227
rmuller Avatar asked Dec 31 '14 09:12

rmuller


2 Answers

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.

like image 103
Mohammad Alavi Avatar answered Nov 04 '22 18:11

Mohammad Alavi


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);
        }
    };
}
like image 1
P.J.Meisch Avatar answered Nov 04 '22 18:11

P.J.Meisch