首页 > 解决方案 > 没有显式调用的方法的 Java 堆栈帧(调用站点)

问题描述

我有一个关于 Java 程序执行时出现在堆栈上的方法的问题。我已经对代码进行了检测,以记录方法执行何时开始,以及方法何时退出(考虑之前和之后的 AOP)。我为每个线程创建一个日志。结果大多与预期一致,但有一些细微差别。

  1. 当遇到反射调用时,不仅java.lang.reflect.Method#invoke会记录下来,还会记录其他调用,例如sun.reflect.DelegatingMethodAccessorImpl#invoke显示。我认为这与StackWalker文档中讨论的隐藏帧有关。
  2. 还有其他调用,主要是java.lang.ClassLoader.loadClass,但也有sun.instrument.InstrumentationImpl.transform(请记住,我检测代码!)。这些是具有堆栈帧的方法,但应用程序类中没有调用站点。

我有两个问题:

  1. 是否有所有方法的列表,或定义将隐藏调用的方法的标准(例如“在以 开头的包中的类中定义的所有方法sun.)?
  2. 是否有所有方法的列表,或定义由 JVM 调用的方法的标准,而用户代码中没有调用站点?

谢谢

标签: javareflectionjvminvoke

解决方案


  1. sun.reflect.DelegatingMethodAccessorImpl#invoke和朋友没什么特别的。这些是在 Java 代码中具有常规调用站点的普通 Java 方法。

  2. 确实,某些 Java 方法是直接从 VM 代码调用的。这样的电话有很多,要得到完整的名单并不容易。

    在 HotSpot 源代码中查找JavaCalls::call_virtualJavaCalls::call_static等。JavaCalls::call_special例如,这里是对提到的ClassLoader.loadClass.

    实际上,任何方法都可以通过这种方式调用。即使您设法获得完整列表,它也不会很有用,因为它可能会在任何次要的 JDK 更新中发生变化。

    此外,用户代码和代理库还可以使用 JNI 调用任何 Java 方法,并且这些调用也不会有可见的 Java 调用站点。


推荐阅读