我正在寻找一种方法,通过使用Java代理或检测类(最好是比用户类更低级别的东西)拦截JVM中的所有对象创建(new
或任何其他创建Object的方法),是similar question,它不关注Java代理或低于检测用户类的东西
答案 0 :(得分:16)
可以通过几种不同的方式创建Java对象。
new
,newarray
,anewarray
, multianewarray
。NewObject
,NewObjectArray
,NewStringUTF
,{ {3}}等等。Object.clone()
,Throwable.getStackTrace()
,Class.getInterfaces()
等不幸的是,没有一点可以从所有这些来源收集对象。但是,有办法拦截所有这些。
从Java实例化的对象可以被NewDirectByteBuffer
代理捕获。代理需要定义一个Instrumentation,它将扫描所有已加载类的字节码以获取对象创建指令并进行修改。
注意:无需拦截所有new
指令,您可以改为使用Object()
构造函数。但是你仍然需要拦截数组分配指令。
JVMI代理可以拦截JNI函数。您需要为NewObjectArray
,NewStringUTF
等定义自己的本机挂钩,然后替换JNI函数表。有关详细信息,请参阅ClassFileTransformer。
VM创建的对象可以被JVMTI Reference捕获。所需的事件是JVMTI Event Callback mechanism。
注意:对于从Java或JNI函数分配的对象,JVM不会发布VMObjectAlloc
事件。
对象实例化(克隆,反射,反序列化)的所有其他方式都属于上述类别之一。
从Oracle VMObjectAlloc网站获取JDK 8演示和示例 正是这个问题有一个样本JVMTI代理。
在
下查看jvmti/heapTracker
jvmti/hprof
答案 1 :(得分:2)
您可以查看由devexperts团队创建的这个opensource java代理 https://github.com/Devexperts/aprof 它提供了很好的报告来检测内存的分配位置。但是,据我所知,它不会拦截通过JNI创建的新对象或当前版本中的sun.misc.Unsafe.allocateInstance
使用ASM操作字节码的纯java代理。在每个对象分配之前,aprof会插入方法调用,该方法调用会分配大小和位置堆栈(发生此分配的位置)