zoukankan      html  css  js  c++  java
  • Instrumentation: querying the memory usage of a Java object

    Copy from: http://www.javamex.com/tutorials/memory/instrumentation.shtml

    Instrumentation: querying the memory usage of a Java object

    The most reliable— but not necessarily the easiest— way to estimate the usage of a Java object is to ask the JVM. Querying the JVM for the memory usage of an object requires the Instrumentation framework introduced in Java 5. Hotspot supports the instrumentation framework; if you use a VM from a different vendor, it will need to provide similar support, and there may be some variation in the procedures described here. The general idea is:

    • we create a special agent class with a special premain method, generally compiling it against the rest of our code so that it can see the definitions of the classes whose memory usage we're interested in measuring;
    • the JVM passes a special Instrumentation object to our premain method, which we can use to query the size of an object;
    • we package the compiled agent class into a jar with a special manifest file;
    • we run our program, passing in the agent jar to the VM command line arguments.

    On the rest of this page, we'll go through the above procedure step by step.

    1. Creating the instrumentation agent class

    An instrumentation agent is a class with a special method, with a predefined signature, that the JVM will invoke before the rest of the application for you to set up any instrumentation code. Generally, instrumentation is the act of transforming classes for profiling purposes: for example, we could manipulate the definition of the String class to increment a counter every time a string is created, and thus measure e.g. how many strings per second our application creates. But an interesting additional feature provided by the instrumentation framework is the ability to measure the memory usage of an object.

    Our agent is simply a class with the following method defined:

    public static void premain(String args, Instrumentation inst) {
      ...
    }
    

    The JVM will pass to our method an implementation of the Instrumentation interface, defined in java.lang.instrument. In turn, this interface defines the method getObjectSize(). So for example, if we want to measure the memory usage of an instance of SomeClass, our agent code would look as follows:

    import java.lang.instrument.*;
    import com.somepackage.SomeClass;
    
    public class MyAgent {
      public static void premain(String args, Instrumentation inst) {
        SomeClass obj = new SomeClass();
        long size = inst.getObjectSize(obj);
        System.out.println("Bytes used by object: " + size);
      }
    }
    

    Note that there's no interface that our agent needs to define: we just need to make sure that we get the method signature correct so that the JVM will find it.

    2. Package the agent into a jar

    Once we have compiled our agent class, we need to package it into a jar. This step is slightly fiddly, because we also need to create a manifest file. The latter is simple a text file containing a single line that specifies the agent class. For example, you can create a file called manifest.txt with the following line:

    Premain-Class: mypackage.MyAgent
    

    Then, to create the jar, we execute the following command (it's usually worth creating a batch file or shell script with this line in case you need to re-build the agent jar several times):

    jar -cmf manifest.txt agent.jar mypackage/MyAgent.class
    

    3. Run the application with the agent

    Now, we execute the application as usual, but use the javaagent command line argument to specify that we want to attach our instrumentation agent. For example, assuming the classpath is the current directory and that the application's main method is in com.mypackage.Main:

    java -javaagent:agent.jar -cp . com.mypackage.Main
    

    Now, before our application is run, our agent's premain method will be run. And in this case, the size of an instance of SomeClass will be created.

    Accessing the Instrumentation object from within our application

    In our simple example above, we measured the size of an object created during the execution of the premain method. But what if we want to measure the size of an object during the lifetime of the application? Well, we can still do so; we just need to arrange for the rest of our application to see theInstrumentation object passed to the premain method. This works because the single agent class (and the Instrumentation instance) created at startup remains valid throughout the application. So we can simple store the Instrumentation instance in a static variable, then provide a static method to access it. For example:

    public class MyAgent {
      private static volatile Instrumentation globalInstr;
      public static void premain(String args, Instrumentation inst) {
        globalInstr = inst;
      }
      public static long getObjectSize(Object obj) {
        if (globalInstr == null)
          throw new IllegalStateException("Agent not initted");
        return globalInstr.getObjectSize(obj);
      }
    }
    

    Now, provided the agent is included in the JVM command line parameters as above, then from anywhere in our application we can callMyAgent.getObjectSize() to query the memory size of an object created by our Java application.

    Calculating "deep" memory usage of an object

    Note that the getObjectSize() method does not include the memory used by other objects referenced by the object passed in. For example, if Object A has a reference to Object B, then Object A's reported memory usage will include only the bytes needed for the reference to Object B (usually 4 bytes), not the actual object.

    To get a "deep" count of the memory usage of an object (i.e. which includes "subobjects" or objects referred to by the "main" object), then you can use the Classmexer agent available for beta download from this site.

  • 相关阅读:
    关于分布式事务、两阶段提交协议、三阶提交协议(转)
    高并发下产生大量,随机,唯一的字符串,并输出到文件中
    地理空间距离计算优化_附近的人(转自美团技术博客)
    Web Deploy发布网站错误 检查授权和委派设置
    mssql查询所有上下级
    mssql语句递归查找所有下级
    挖洞技巧:任意账号密码重置
    MAC卸载java 12.0.2
    mac  安装brew时报错的问题及解决方式
    致远getshell
  • 原文地址:https://www.cnblogs.com/hellotech/p/3952878.html
Copyright © 2011-2022 走看看