如何拦截 Java 低于用户 class 级别的对象创建
How to intercept object creation in Java lower than user class level
我正在寻找一些方法,通过使用 Java 代理或检测 类(最好是比用户 类 级别低的东西)来拦截 JVM 中的所有对象创建(new
或创建对象的任何替代方法),有一个 similar question 不关注 Java 代理或低于检测用户的东西 类
Java 可以用几种不同的方式创建对象。
- 来自 Java 代码 ,当 Java 方法(解释或编译)执行以下字节码指令之一时:
new
, newarray
, anewarray
, multianewarray
.
- 从本机代码,当本机方法(包括标准 class 库中的方法)调用 JNI 函数之一:
NewObject
, NewObjectArray
, NewStringUTF
, NewDirectByteBuffer
等时
- 直接从 VM 运行时,当 JVM 内部创建新对象时,例如响应
Object.clone()
、Throwable.getStackTrace()
、Class.getInterfaces()
,等等
不幸的是,没有一个点可以让您从所有这些来源收集对象。但是,有办法拦截所有这些。
从 Java 实例化的对象可以被 Instrumentation agent. The agent needs to define a ClassFileTransformer 捕获,它将扫描所有加载的 classes 的字节码以获取对象创建指令并修改它.
注意:无需拦截所有 new
指令,您可以使用 Object()
构造函数代替。但是还是需要拦截数组分配指令。
JNI 函数可以被 JVMTI 代理拦截。您需要为 NewObjectArray
、NewStringUTF
等定义自己的本机挂钩,然后替换 JNI 函数 table。有关详细信息,请参阅 JVMTI Reference。
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 插入方法调用,该方法调用跟踪分配大小和位置堆栈(发生此分配的位置)
我正在寻找一些方法,通过使用 Java 代理或检测 类(最好是比用户 类 级别低的东西)来拦截 JVM 中的所有对象创建(new
或创建对象的任何替代方法),有一个 similar question 不关注 Java 代理或低于检测用户的东西 类
Java 可以用几种不同的方式创建对象。
- 来自 Java 代码 ,当 Java 方法(解释或编译)执行以下字节码指令之一时:
new
,newarray
,anewarray
,multianewarray
. - 从本机代码,当本机方法(包括标准 class 库中的方法)调用 JNI 函数之一:
NewObject
,NewObjectArray
,NewStringUTF
,NewDirectByteBuffer
等时 - 直接从 VM 运行时,当 JVM 内部创建新对象时,例如响应
Object.clone()
、Throwable.getStackTrace()
、Class.getInterfaces()
,等等
不幸的是,没有一个点可以让您从所有这些来源收集对象。但是,有办法拦截所有这些。
从 Java 实例化的对象可以被 Instrumentation agent. The agent needs to define a ClassFileTransformer 捕获,它将扫描所有加载的 classes 的字节码以获取对象创建指令并修改它.
注意:无需拦截所有
new
指令,您可以使用Object()
构造函数代替。但是还是需要拦截数组分配指令。JNI 函数可以被 JVMTI 代理拦截。您需要为
NewObjectArray
、NewStringUTF
等定义自己的本机挂钩,然后替换 JNI 函数 table。有关详细信息,请参阅 JVMTI Reference。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 插入方法调用,该方法调用跟踪分配大小和位置堆栈(发生此分配的位置)