{"id":195,"date":"2019-08-22T08:39:07","date_gmt":"2019-08-22T08:39:07","guid":{"rendered":"https:\/\/openapex.org\/spaces\/software\/?p=195"},"modified":"2022-02-24T20:25:26","modified_gmt":"2022-02-24T14:55:26","slug":"how-to-use-the-java-instrumentation-api-to-determine-object-size","status":"publish","type":"post","link":"https:\/\/mutesoft.com\/spaces\/software\/how-to-use-the-java-instrumentation-api-to-determine-object-size.html","title":{"rendered":"How to use the Java Instrumentation API to determine object size?"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"512\" src=\"https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation-1024x512.jpg\" alt=\"The instrumentation tools\" class=\"wp-image-1032\" srcset=\"https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation-1024x512.jpg 1024w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation-300x150.jpg 300w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation-768x384.jpg 768w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation-1536x768.jpg 1536w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation-500x250.jpg 500w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation-800x400.jpg 800w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation-1280x640.jpg 1280w, https:\/\/mutesoft.com\/spaces\/software\/wp-content\/uploads\/sites\/7\/2022\/02\/instrumentation.jpg 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/mutesoft.com\/spaces\/software\/how-to-use-the-java-instrumentation-api-to-determine-object-size.html\/#1_What_is_Java_agent\" >1. What is Java agent?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/mutesoft.com\/spaces\/software\/how-to-use-the-java-instrumentation-api-to-determine-object-size.html\/#2_Starting_Java_agent\" >2. Starting Java agent<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/mutesoft.com\/spaces\/software\/how-to-use-the-java-instrumentation-api-to-determine-object-size.html\/#3_Creating_Java_agent\" >3. Creating Java agent<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/mutesoft.com\/spaces\/software\/how-to-use-the-java-instrumentation-api-to-determine-object-size.html\/#4_Determine_Object_size\" >4. Determine Object size<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/mutesoft.com\/spaces\/software\/how-to-use-the-java-instrumentation-api-to-determine-object-size.html\/#5_Byte-code_modification\" >5. Byte-code modification<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/mutesoft.com\/spaces\/software\/how-to-use-the-java-instrumentation-api-to-determine-object-size.html\/#6_Conclusion\" >6. Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\" id=\"1-what-is-java-agent\"><span class=\"ez-toc-section\" id=\"1_What_is_Java_agent\"><\/span><strong>1. What is Java agent?<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In Java 1.5 <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/instrument\/package-summary.html\" target=\"_blank\">Instrumentation API<\/a>  was introduced (<code>java.lang.instrument<\/code> package) to enable byte-code modification (instrumentation) of classes and to get runtime insights. This is very helpful to tool developers. In this article, we&#8217;ll see how  <a rel=\"noreferrer noopener\" aria-label=\"Java Instrumentation API (opens in a new tab)\" href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/instrument\/package-summary.html\" target=\"_blank\">Instrumentation API<\/a> can be leveraged to determine approximate object size at runtime.<\/p>\n\n\n\n<p>Java agent is packaged as a plain Jar containing a set of classes having some specific methods. When an application is run with a Java agent, the agent performs the required instrumentations.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"2-starting-java-agent\"><span class=\"ez-toc-section\" id=\"2_Starting_Java_agent\"><\/span><strong>2. Starting Java agent<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Java agent can be started either statically or dynamically in a running JVM. To start Java agent statically, add the <code>javaagent<\/code> option while launching the application:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"atomic\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">java -javaagent:myagent.jar org.openapex.samples.misc.instrument.ObjectSize<\/pre>\n\n\n\n<p>To start a Java agent in a running JVM, do the following:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">VirtualMachine vm = VirtualMachine.attach(jvmPid); \/\/ target JVM PID\nvm.loadAgent(agentFile.getAbsolutePath());<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"3-creating-java-agent\"><span class=\"ez-toc-section\" id=\"3_Creating_Java_agent\"><\/span><strong>3. Creating Java agent<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>If you plan to start the Java agent statically, then create a class with the following <code>premain<\/code> method. This method is called by the JVM to start the agent.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class MyInstrumentationAgent {\n    public static void premain(String agentArgs, Instrumentation inst){\n        System.out.println(\"Set the instrumentation from premain\");\n        \/\/ Attach class transformers\n    }\n}<\/pre>\n\n\n\n<p>In case you plan to start the Java agent dynamically, then create a class with the following <code>agentmain<\/code> method. This method is called by the JVM to start the agent.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class MyInstrumentationAgent {\n    public static void agentmain(String agentArgs, Instrumentation inst){\n        System.out.println(\"Set the instrumentation from agentmain\");\n        \/\/ Attach class transformers\n    }\n}<\/pre>\n\n\n\n<p>If you want to have the flexibility to start the agent both statically and dynamically, you may define both the methods in the same class. <\/p>\n\n\n\n<p>Now, create a JAR in the usual way using <code>jar<\/code> command and ensure the following entries (<code>Premain-class<\/code> and <code>Agent-class<\/code>) are present in the manifest file.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"ini\" data-enlighter-theme=\"atomic\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Premain-Class: org.openapex.samples.misc.instrument.MyInstrumentationAgent\nAgent-Class: org.openapex.samples.misc.instrument.MyInstrumentationAgent\n<\/pre>\n\n\n\n<p>Create the agent JAR:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"atomic\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">jar -cvfm myagent.jar manifest.txt org\/openapex\/samples\/misc\/instrument\/MyInstrumentationAgent.class<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"4-determine-object-size\"><span class=\"ez-toc-section\" id=\"4_Determine_Object_size\"><\/span><strong>4. Determine Object size<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In the previous sections, we have seen what is Java agent and how to create one for instrumentation. Let us see how we can create a Java agent and leverage <code>Instrumentation.getObjectSize(obj)<\/code> to determine object size.  Define an agent class with both <code>premain()<\/code> and <code>agentmain()<\/code> methods. Keep the reference of <code>Instrumentation<\/code> object and later use it to get the object size.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">package org.openapex.samples.misc.instrument;\n\nimport java.lang.instrument.Instrumentation;\n\npublic class MyInstrumentationAgent {\n    private static Instrumentation instrumentation;\n\n    public static void premain(String agentArgs, Instrumentation inst){\n        instrumentation = inst;\n        System.out.println(\"Set the instrumentation from premain\");\n    }\n    public static void premain(String agentArgs){\n        System.out.println(\"Unable to set instrumentation premain\");\n    }\n\n    public static void agentmain(String agentArgs, Instrumentation inst){\n        instrumentation = inst;\n        System.out.println(\"Set the insttrumentation from agentmain\");\n    }\n    public static void agentmain(String agentArgs){\n        System.out.println(\"Unable to set instrumentation agentmain\");\n    }\n\n    public static long getObjectSize (Object object){\n        if (instrumentation != null){\n            return instrumentation.getObjectSize(object);\n        }\n        System.out.println(\"Unable to determine object size, instrumentation is not available\");\n        return 0;\n    }\n}<\/pre>\n\n\n\n<p>Let us define the application class that will determine object size. In this example, we get the approximate object size of a <code>File<\/code>, <code>String<\/code> and <code>Integer<\/code>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">package org.openapex.samples.misc.instrument;\n\nimport java.io.File;\nimport java.lang.instrument.Instrumentation;\n\npublic class ObjectSize {\n    public static void main(String[] args) {\n        File f = new File(\"data\/user.csv\");\n        String hello = \"Hello World\";\n        Integer num = Integer.valueOf(100);\n        System.out.println(\"Size of file object: \" + MyInstrumentationAgent.getObjectSize(f));\n        System.out.println(\"Size of file string: \" + MyInstrumentationAgent.getObjectSize(hello));\n        System.out.println(\"Size of file integer: \" + MyInstrumentationAgent.getObjectSize(num));\n    }\n}<\/pre>\n\n\n\n<p>Start the application by adding <code>javaagent<\/code> option:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"atomic\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">java -javaagent:myagent.jar org.openapex.samples.misc.instrument.ObjectSize<\/pre>\n\n\n\n<p>Here is the output from <code>ObjectSize<\/code> application:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"atomic\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Size of file object (bytes): 32\nSize of string (bytes): 24\nSize of integer (bytes): 16<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"5-byte-code-modification\"><span class=\"ez-toc-section\" id=\"5_Byte-code_modification\"><\/span><strong>5. Byte-code modification<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>If you want to modify byte-code from your Java agent, create one or more <code>ClassFileTransformer<\/code> and add these to the <code>Instrumentation<\/code> object from <code>premain()<\/code> or <code>agentmain()<\/code> methods.<\/p>\n\n\n\n<p>The <code>ClassFileTransormer<\/code> looks like:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public class MyClassTransformer implements ClassFileTransformer{\n    @Override\n    public byte[] transform(ClassLoader loader, String className, Class&lt;?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {\n        \/\/ Here change the byte code as needed\n        byte[] newbytes = new byte[100];\n        return newbytes;\n    }\n}<\/pre>\n\n\n\n<p>Add the transformer to the <code>Instrumentation<\/code> object:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">public static void premain(String agentArgs, Instrumentation inst){\n    instrumentation = inst;\n    System.out.println(\"Set the instrumentation from premain\");\n    instrumentation.addTransformer(new MyClassTransformer());\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"6-conclusion\"><span class=\"ez-toc-section\" id=\"6_Conclusion\"><\/span><strong>6. Conclusion<\/strong><span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In this article, we have seen how to create a simple Java agent and use it in an application. The possible uses cases of instrumentation are limitless. The source code, manifest file, agent Jar files can be downloaded from <a href=\"https:\/\/github.com\/fiveobjects\/reference\/tree\/master\/java\/misc\/src\/main\/java\/org\/openapex\/samples\/misc\/instrument\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"GitHub (opens in a new tab)\">GitHub<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Java 1.5 Instrumentation API  was introduced to enable byte-code modification (instrumentation) of classes and to get runtime insights. This is very helpful to tool developers. In this article, we&#8217;ll see how  Instrumentation API can be leveraged to determine approximate object size at runtime.<\/p>\n","protected":false},"author":2,"featured_media":1032,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"none","_seopress_titles_title":"","_seopress_titles_desc":"In Java 1.5 Instrumentation API  was introduced to enable byte-code modification (instrumentation) of classes and to get runtime insights. This is very helpful to tool developers. In this article, we&#039;ll see how  Instrumentation API can be leveraged to determine approximate object size at runtime.","_seopress_robots_index":"","_vp_format_video_url":"","_vp_image_focal_point":[],"footnotes":""},"categories":[6],"tags":[9,36],"class_list":["post-195","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming","tag-java","tag-tools"],"_links":{"self":[{"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/posts\/195","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/comments?post=195"}],"version-history":[{"count":20,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/posts\/195\/revisions"}],"predecessor-version":[{"id":1103,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/posts\/195\/revisions\/1103"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/media\/1032"}],"wp:attachment":[{"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/media?parent=195"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/categories?post=195"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mutesoft.com\/spaces\/software\/wp-json\/wp\/v2\/tags?post=195"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}