
JAVA_OPTS=-javaagent:[path/to/]jrebel.jar or so -javaagent:/path-to/plumbr.jarjava.lang.instrument ) at runtime. This is if in brief. Official documentation can be read here , but it is rather scarce. Nothing is clear? So, let's understand. It is best to understand the examples. package ru.habrahabr.agent; public class Agent007 { public static void premain(String args) { System.out.println("Hello! I`m java agent"); } } public static void premain(String args);public static void premain(String args, Instrumentation inst);MANIFEST.MF , with the required attribute Manifest-Version: 1.0 PreMain-Class: ru.habrahabr.agent.Agent007 don't forget to add a newline to the end of the file jar -cvfm Agent007.jar manifest.mf ru/habrahabr/agent/Agent007.class package ru.habrahabr.agent; public class AgentTester { public static void main(String[] args) { System.out.println("Hello! I`m agent tester"); } } java -javaagent:Agent007.jar ru.habrahabr.agent.AgentTester Hello! I`m java agent Hello! I`m agent tester -javaagent:jarpath[=options] parameter -javaagent:jarpath[=options] package ru.habrahabr.agent; import java.lang.instrument.Instrumentation; public class AgentCounter { public static void premain(String agentArgument, Instrumentation instrumentation) { System.out.println("Agent Counter"); instrumentation.addTransformer(new ClassTransformer()); } } java.lang.instrument.ClassFileTransformer interface and add your object via the Instrumentation.addTransformer method package ru.habrahabr.agent; import java.lang.instrument.ClassFileTransformer; import java.security.ProtectionDomain; public class ClassTransformer implements ClassFileTransformer { private static int count = 0; @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { System.out.println("load class: " + className.replaceAll("/", ".")); System.out.println(String.format("loaded %s classes", ++count)); return classfileBuffer; } } jar -cvfm agentCounter.jar manifest.mf ru/habrahabr/agent/AgentCounter.class ru/habrahabr/agent/ClassTransformer.class package ru.habrahabr.agent; public class AgentTester { public static void main(String[] args) { A a = new A(); B b = new B(); C c = null; } } class A {}; class B {}; class C {}; java -javaagent:agentCounter.jar ru.habrahabr.agent.AgentTester Agent Counter load class: sun.launcher.LauncherHelper loaded 1 classes load class: ru.habrahabr.agent.AgentTester loaded 2 classes load class: ru.habrahabr.agent.A loaded 3 classes load class: ru.habrahabr.agent.B loaded 4 classes results may vary for different versions of java sun.reflect.GeneratedMethodAccessor230 loaded 33597 classes java.rmi.server.Unreferenced loaded 33598 classes Instrumentation interface there is a remarkable long getObjectSize(Object objectToSize) that returns the size of the object. But how to get access to the agent from our application? And we don’t have to do anything special, the javaagent is automatically added to the classpath and all we have to do is add an instrumentation instrumentation field to the agent and initialize it in the premain method. package ru.habrahabr.agent; import java.lang.instrument.Instrumentation; public class AgentMemoryCounter { private static Instrumentation instrumentation; public static void premain(String args, Instrumentation instrumentation) { AgentMemoryCounter.instrumentation = instrumentation; } public static long getSize(Object obj) { if (instrumentation == null) { throw new IllegalStateException("Agent not initialised"); } return instrumentation.getObjectSize(obj); } } AgentMemoryCounter.getSize(obj) method from an application class. package ru.habrahabr.agent; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Calendar; public class AgentTester { public static void main(String[] args) { printObjectSize(new Object()); printObjectSize(new A()); printObjectSize(1); printObjectSize("string"); printObjectSize(Calendar.getInstance()); printObjectSize(new BigDecimal("999999999999999.999")); printObjectSize(new ArrayList<String>()); printObjectSize(new Integer[100]); } public static void printObjectSize(Object obj) { System.out.println(String.format("%s, size=%s", obj.getClass() .getSimpleName(), AgentMemoryCounter.getSize(obj))); } } class A { Integer id; String name; } java -javaagent:agentMemoryCounter.jar ru.habrahabr.agent.AgentTester Agent Counter Object, size=8 A, size=16 Integer, size=16 String, size=24 GregorianCalendar, size=112 BigDecimal, size=32 ArrayList, size=24 Integer[], size=416 getObjectSize() method does not take into account the size of the nested objects, that is, only the memory spent on the object reference is taken into account.Source: https://habr.com/ru/post/230239/
All Articles