@CallerSensitive 注解的做用

在java的 Class类forName方法上,有个CallerSensitive注解。java

@CallerSensitive
public static Class<?> forName(String className)
            throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass();
    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

能够发现 Class.forName 方法上有 @CallerSensitive 注解, 由于代码里的Reflection.getCallerClass()这个native方法要求。c++

@CallerSensitive
public static native Class<?> getCallerClass();

见 http://openjdk.java.net/jeps/176 。
总结就是说 jdk内有些方法,jvm的开发者认为这些方法危险,不但愿开发者调用,就把这种危险的方法用 @CallerSensitive修饰,并在“jvm”级别检查。bootstrap

如Reflection.getCallerClass()方法规定,调用它的对象,必须有 @CallerSensitive 注解,不然 报异常 Exception in thread "main" java.lang.InternalError: CallerSensitive annotation expected at frame 1
@CallerSensitive 有个特殊之处,必须由 启动类classloader加载(如rt.jar ),才能够被识别。 因此rt.jar下面的注解能够正常使用。
开发者本身写的@CallerSensitive 不能够被识别。 可是,能够利用jvm参数 -Xbootclasspath/a: path 伪装本身的程序是启动类。jvm

测试若是下测试

/*有CallerSensitive注解*/
@CallerSensitive
public static void withCallerSensitive() {
    System.out.format("Method is called by %s%n",Reflection.getCallerClass());
}

/*无注解直接调用*/
public static void noCallerSensitive() {
    System.out.format("Method is called by %s%n",Reflection.getCallerClass());
}

执行上面任意方法,都会报 java.lang.InternalError: CallerSensitive annotation expected at frame 1。spa


添加jvm 启动参数,而后再测试下面的方法.net

/* 执行前jvm 添加参数 -Xbootclasspath/a:D:\workspace\demo\target\classes */
@CallerSensitive
public static void withCallerSensitiveAndJvmParam() {
    System.out.format("Method is called by %s%n",Reflection.getCallerClass());
}

就会正确地显示 Method is called by class rt.java.lang.ClassDemo。orm

PS1: -Xbootclasspath介绍对象

-Xbootclasspath:bootclasspath :让jvm从指定的路径中加载bootclass,用来替换jdk的rt.jar。通常不会用到。
         -Xbootclasspath/a: path : 被指定的文件追加到默认的bootstrap路径中。
         -Xbootclasspath/p: path : 让jvm优先于默认的bootstrap去加载path中指定的class。

PS2:加载器介绍blog

  • 启动类加载器Bootstrap ClassLoader:加载JRE_HOME/lib下的核心包,该类加载器是用c++写的。
  • 扩展类加载器Extension ClassLoader:加载JRE_HOME/lib/ext目录下的扩展包,也能够经过启动参数-Djava.ext.dirs指定,该类用java编写。对应ExtClassLoader
  • 应用类加载器Application ClassLoader:应用类加载器,加载classpath下的字节码文件,用java编写,对应AppClassLoader这个类,能够经过ClassLoader类的静态方法getSystemClassLoader()得到,因此又叫系统类加载器
  • 自定义类加载器:自定义的类加载器,经过直接或者间接继承抽象的ClassLoader类。
相关文章
相关标签/搜索