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

2022-01-16 00:00:00 jvm java

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

解决方案

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

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

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

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

    注意:不需要拦截所有的 new 指令,您可以使用 Object() 构造函数代替.但是你仍然需要拦截数组分配指令.

  2. JNI 函数可以被 JVMTI 代理拦截.您需要为 NewObjectArrayNewStringUTF 等定义自己的原生钩子,然后替换 JNI 函数表.有关详细信息,请参阅 JVMTI 参考.p>

  3. VM 创建的对象可以被 JVMTI 事件回调机制.所需的事件是 VMObjectAlloc.

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

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


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

往下看

  • jvmti/heapTracker
  • jvmti/hprof

I am looking towards some approach where by using Java agent or instrumenting classes (preferably something at lower level than user classes) to intercept all object creation in JVM (new or any alternative ways to create Object), There is a similar question which doesn't focus on Java agent or something lower than instrumenting user classes

解决方案

Java Objects can be created in several different ways.

  1. From Java code, when a Java method, either interpreted or compiled, executes one of the following bytecode instructions: new, newarray, anewarray, multianewarray.
  2. From native code, when native methods, including those in standard class library, call one of JNI functions: NewObject, NewObjectArray, NewStringUTF, NewDirectByteBuffer, etc.
  3. Directly from VM runtime, when a new object is created internally by JVM, for example, in response to Object.clone(), Throwable.getStackTrace(), Class.getInterfaces(), etc.

Unfortunately, there is no single point where you can collect objects from all these sources. However, there are means for intercepting all of them.

  1. Objects instantiated from Java can be caught by an Instrumentation agent. The agent needs to define a ClassFileTransformer that will scan the bytecode of all loaded classes for object-creating instructions and modify it.

    Note: there is no need to intercept all new instructions, you can instrument Object() constructor instead. But you still need to intercept array allocation instructions.

  2. JNI functions can be intercepted by JVMTI agent. You need to define your own native hooks for NewObjectArray, NewStringUTF etc. and then replace JNI function table. See JVMTI Reference for the details.

  3. Objects created by the VM can be caught by JVMTI Event Callback mechanism. The desired event is VMObjectAlloc.

    Note: JVM will not post VMObjectAlloc event for objects allocated from Java or by JNI functions.

All other ways of object instantiation (cloning, reflection, deserialization) fall into one of the above categories.


Get JDK 8 Demos and Samples from Oracle Java SE Downloads website.
There is a sample JVMTI agent for exactly this question.

Look under

  • jvmti/heapTracker
  • jvmti/hprof

相关文章