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

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

可以通过多种不同方式创建Java对象。

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

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

  1. 从Java实例化的对象可以由Instrumentation代理捕获。 代理需要定义一个ClassFileTransformer ,它将扫描所有已加载类的字节码以获取对象创建指令并对其进行修改。

    注意:没有必要拦截所有new指令,你可以改为使用Object()构造函数。 但是你仍然需要拦截数组分配指令。

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

  3. VM创建的对象可以通过JVMTI事件回调机制捕获。 所需的事件是VMObjectAlloc 。

    注意:JVM不会为从Java或JNI函数分配的对象发布VMObjectAlloc事件。

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


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

看下

  • jvmti/heapTracker
  • jvmti/hprof

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

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