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

时间:2016-03-10 18:21:01

标签: java jvm

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

2 个答案:

答案 0 :(得分:16)

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

  1. 从Java代码,当Java方法(解释或编译)执行以下字节码指令之一时:newnewarrayanewarraymultianewarray
  2. 从本机代码,当本机方法(包括标准类库中的方法)调用JNI函数之一时:NewObjectNewObjectArrayNewStringUTF,{ {3}}等等。
  3. 直接来自VM运行时,当JVM在内部创建新对象时,例如,响应Object.clone()Throwable.getStackTrace()Class.getInterfaces()
  4. 不幸的是,没有一点可以从所有这些来源收集对象。但是,有办法拦截所有这些。

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

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

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

    3. VM创建的对象可以被JVMTI Reference捕获。所需的事件是JVMTI Event Callback mechanism

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

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

      从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会插入方法调用,该方法调用会分配大小和位置堆栈(发生此分配的位置)