我是靠谱客的博主 敏感皮皮虾,最近开发中收集的这篇文章主要介绍@CallerSensitive 注解的作用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

在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 注解的作用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(63)

评论列表共有 0 条评论

立即
投稿
返回
顶部