我是靠谱客的博主 犹豫白猫,最近开发中收集的这篇文章主要介绍java sun包无法引用_【转载】为什么不建议调用sun包,如何通过其他方法确定调用者...,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

获取调用者信息的方法

一般的,我们可以通过堆栈信息获取调用当前方法的类名和方法名

// 通过堆栈信息获取调用当前方法的类名和方法名

String className = “”;

String methodName = “”;

Class clazz = null;

StackTraceElement[] elements = new Throwable().getStackTrace();

for (int i = 0; i < elements.length; i++){

if (this.getClass().getName().equals(elements[i].getClassName())){

// 获取堆栈的下一个元素,就是调用者元素

// 如果想要获取当前方法所在类的信息,直接读取elements[i]就可以了

className = elements[i + 1].getClassName();

methodName = elements[i + 1].getMethodName();

break;

}

}

System.out.println(className + “.” + methodName + “n”);

该方法也可以获取调用代码所在的行号的类所在的文件,但是这种方法不能获得调用者的类型,因为不知道调用者的的类装载器,所以也就不能使用Class.forName(String)得到类型。

可以尝试使用以下方法获得调用者的类型(但该方法不建议使用,后面有说明)

clazz = Reflection.getCallerClass(2);

System.out.println(“invoker’s class loader: “ + clazz.getClassLoader() + “nclass name: “ + clazz.getName());

该方法比使用堆栈的效率高,如果想要获取当前方法所在类的信息,调用 Reflection.getCallerClass(1) 就可以了,Reflection.getCallerClass(0) 是Reflection对象

为什么不建议调用sun包

这篇文章中提到了JDK 8弃用 sun.reflect.Reflection.getCallerClass:

但后来Oracle又决定把该方法保留下来了:

JDK 8 实际上新特性如下

其中 JEP 176:自动检测识别Caller-Sensitive方法:

JDK 8中在getCallerClass方法加了 @sun.reflect.CallerSensitive 注解,该注解是提供给JVM底层读取处理的,提高了JDK实现感知调用者功能的安全性,详细参考:

查看getCallerClass的 底层实现 #668可以发现,当传入了depth的时候,调用了net.reflect.Reflection类的这个方法:

@java.lang.Deprecated

public static native java.lang.Class getCallerClass(int arg0);

这个方法在底层实现中还是通过兼容旧版本的代码去执行的,所以这个方法加了一个 @Deprecated 注解,这也是为什么不推荐上面那种方法获取调用者类型的原因。

类似的, JDK8 中的 @java.lang.Class 的 forName(className) 方法也加了这个注解,因为forName方法里面也调用给到了Reflection.getCallerClass()

Oracle建议开发人员不要使用sun包,但是有一系列的项目都依赖于getCallerClass()方法,如Jigsaw和Lambda,Intellij IDEA。在spring-loaded的源码这里也调用了getCallerClass()方法,作为临时的方案去兼容JDK 7u25,需要添加系统属性:jdk.reflect.allowGetCallerClass,参考这里:

其实查看JDK 7 Reflection的字节码可以发现对这个属性的处理逻辑:

public static java.lang.Class getCallerClass(int arg0);

0 invokestatic sun.misc.VM.allowGetCallerClass() : boolean [216]

3 ifeq 13

6 iload_0 [arg0]

7 iconst_1

8 iadd

9 invokestatic sun.reflect.Reflection.getCallerClass0(int) : java.lang.Class [217]

12 areturn

13 new java.lang.UnsupportedOperationException [112]

16 dup

17 ldc [7]

19 invokespecial java.lang.UnsupportedOperationException(java.lang.String) [206]

22 athrow

Line numbers:

[pc: 0, line: 68]

[pc: 6, line: 69]

[pc: 13, line: 71]

Stack map table: number of frames 1

[pc: 13, same]

开发者不应该调用sun包,Oracle一直在提醒开发者,调用sun.*包里面的方法是危险的。上面用到的Reflection.getCallerClass()也是在这个包里面的,因为sun包并不包含在Java平台的标准中,它与操作系统相关,在不同的操作系统如Solaris,Windows,Linux,Mac等中的实现也各不相同,并且可能随着JDK版本而变化。详细说明:

完整例子:

最后

以上就是犹豫白猫为你收集整理的java sun包无法引用_【转载】为什么不建议调用sun包,如何通过其他方法确定调用者...的全部内容,希望文章能够帮你解决java sun包无法引用_【转载】为什么不建议调用sun包,如何通过其他方法确定调用者...所遇到的程序开发问题。

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

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

评论列表共有 0 条评论

立即
投稿
返回
顶部