如何拦截 Java 低于用户 class 级别的对象创建

How to intercept object creation in Java lower than user class level

我正在寻找一些方法,通过使用 Java 代理或检测 类(最好是比用户 类 级别低的东西)来拦截 JVM 中的所有对象创建(new 或创建对象的任何替代方法),有一个 similar question 不关注 Java 代理或低于检测用户的东西 类

Java 可以用几种不同的方式创建对象。

  1. 来自 Java 代码 ,当 Java 方法(解释或编译)执行以下字节码指令之一时:new, newarray, anewarray, multianewarray .
  2. 从本机代码,当本机方法(包括标准 class 库中的方法)调用 JNI 函数之一:NewObject, NewObjectArray, NewStringUTF, NewDirectByteBuffer 等时
  3. 直接从 VM 运行时,当 JVM 内部创建新对象时,例如响应 Object.clone()Throwable.getStackTrace()Class.getInterfaces(),等等

不幸的是,没有一个点可以让您从所有这些来源收集对象。但是,有办法拦截所有这些。

  1. 从 Java 实例化的对象可以被 Instrumentation agent. The agent needs to define a ClassFileTransformer 捕获,它将扫描所有加载的 classes 的字节码以获取对象创建指令并修改它.

    注意:无需拦截所有 new 指令,您可以使用 Object() 构造函数代替。但是还是需要拦截数组分配指令。

  2. JNI 函数可以被 JVMTI 代理拦截。您需要为 NewObjectArrayNewStringUTF 等定义自己的本机挂钩,然后替换 JNI 函数 table。有关详细信息,请参阅 JVMTI Reference

  3. VM 创建的对象可以被 JVMTI Event Callback mechanism. The desired event is VMObjectAlloc 捕获。

    注意:对于从 Java 或 JNI 函数分配的对象,JVM 不会 post VMObjectAlloc 事件。

对象实例化的所有其他方式(克隆、反射、反序列化)都属于上述类别之一。


从 Oracle Java SE Downloads 网站获取 JDK 8 个演示和示例。
这个问题有一个示例 JVMTI 代理。

往下看

  • jvmti/heapTracker
  • jvmti/hprof

您可以看看这个由开发专家团队创建的开源 java 代理 https://github.com/Devexperts/aprof 它提供了很好的报告来检测内存的分配位置。但是,据我所知,它不会拦截通过 JNI 或当前版本 sun.misc.Unsafe.allocateInstance 创建的新对象

它是纯粹的 java 代理,使用 ASM 操作字节码。在每个对象分配之前,aprof 插入方法调用,该方法调用跟踪分配大小和位置堆栈(发生此分配的位置)