概述
在java的 Class类forName方法上,有个CallerSensitive注解。
@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方法要求。
@CallerSensitive
public static native Class<?> getCallerClass();
见 http://openjdk.java.net/jeps/176 。
总结就是说 jdk内有些方法,jvm的开发者认为这些方法危险,不希望开发者调用,就把这种危险的方法用 @CallerSensitive修饰,并在“jvm”级别检查。
如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 假装自己的程序是启动类。
测试如果下:
/*有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。
添加jvm 启动参数,然后再测试下面的方法
/* 执行前jvm 添加参数 -Xbootclasspath/a:D:workspacedemotargetclasses */
@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。
PS1: -Xbootclasspath介绍
-Xbootclasspath:bootclasspath :让jvm从指定的路径中加载bootclass,用来替换jdk的rt.jar。一般不会用到。 -Xbootclasspath/a: path : 被指定的文件追加到默认的bootstrap路径中。 -Xbootclasspath/p: path : 让jvm优先于默认的bootstrap去加载path中指定的class。
PS2:加载器介绍
- 启动类加载器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类。
最后
以上就是敏感皮皮虾为你收集整理的@CallerSensitive 注解的作用的全部内容,希望文章能够帮你解决@CallerSensitive 注解的作用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复