Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use java-agent

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "how to use java-agent". The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn how to use java-agent.

Static mount

First of all, write the monitoring program of java-agent, and the entry function of static mount is premain. There are two kinds of premain functions, but the difference is that the parameters passed in are different. You usually choose to take the Instrumentation parameter, which you can use to complete a hot replacement of the code.

Public static void premain (String agentArgs, Instrumentation inst); public static void premain (String agentArgs)

Here is a simple example. In the premain function, add a transformer using Instrumentation. Transformer is called every time the monitored java application loads class. DefineTransformer is a transformer and an implementation of ClassFileTransformer. The currently loaded class name, class loader and other information are given in the input parameters of its transform function. In the sample, we just print the name of the loaded class.

Import java.lang.instrument.ClassFileTransformer;import java.lang.instrument.Instrumentation;import java.security.ProtectionDomain;import javassist.*;public class PreMain {public static void premain (String agentArgs, Instrumentation inst) {System.out.println ("agentArgs:" + agentArgs); inst.addTransformer (new DefineTransformer (), true) } static class DefineTransformer implements ClassFileTransformer {@ Override public byte [] transform (ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte [] classfileBuffer) {System.out.println ("premain load Class:" + className) Return classfileBuffer;}

To run java-agent, you need to package the above programs into a jar file, and the MANIFEST.MF of the jar file needs to include the following items

Can-Redefine-Classes: trueCan-Retransform-Classes: truePremain-Class: com.huawei.PreMain

Premain-Class declares the class where the premain function of this jar is located, and java-agent looks for premain in the PreMain class when loading the jar package. Can-Redefine-Classes and Can-Retransform-Classes are declared true, which allows this program to modify the code of the java application.

If you are a project using Maven, you can add MANIFEST.MF automatically by adding the following plug-ins

Org.apache.maven.plugins maven-assembly-plugin 2.6 false jar-with-dependencies true com.huawei.PreMain true true assemble-all package single

After outputting the jar file, write a java application for hello world and compile it to hello.class, using the following command when starting the application

Java-javaagent:/root/Java-Agent-Project-Path/target/JavaAgentTest-1.0-SNAPSHOT.jar hello

During execution, you can print all the classes loaded by the java virtual machine while running hello.class.

The functionality of java-agent is not limited to the loading process of the output class, but the hot replacement of the code can be achieved through the following example. First write a test class.

Public class App {public static void main (String [] args) {try {System.out.println ("main start!"); App test = new App (); int x1 = 1; int x2 = 2; while (true) {System.out.println (Integer.toString (test.add (x1, x2) Thread.sleep (2000);}} catch (InterruptedException e) {e.printStackTrace (); System.out.println ("main end");}} private int add (int x1, int x2) {return x1x2;}}

Then we modify the transformer in the PreMain class and add the transformer through Instrumentation. Same as DefineTransformer.

Static class MyClassTransformer implements ClassFileTransformer {@ Override public byte [] transform (final ClassLoader loader, final String className, final Class classBeingRedefined, final ProtectionDomain protectionDomain) Final byte [] classfileBuffer) {/ / if the currently loaded class is the test class we wrote Enter the modification. If ("com/huawei/App" .equals (className)) {try {/ / get the CtClass object final ClassPool classPool = ClassPool.getDefault () from ClassPool; final CtClass clazz = classPool.get ("com.huawei.App") / / print all member functions in the App class CtMethod [] methodList = clazz.getDeclaredMethods (); for (CtMethod method: methodList) {System.out.println ("premain method:" + method.getName ()) } / / get the add function and replace it. $1 represents the first input parameter of the function CtMethod convertToAbbr = clazz.getDeclaredMethod ("add"); String methodBody = "{return $1 + $2 + 11;}"; convertToAbbr.setBody (methodBody) / / add a piece of code before the body of the add function. Similarly, you can add String methodBody = "System.out.println (Integer.toString ($1)); convertToAbbr.insertBefore (methodBody) at the end of the function. / / the bytecode is returned, and the detachCtClass object byte [] byteCode = clazz.toBytecode (); / / detach means to remove the Date object that has been loaded by javassist in memory, and if it is not found in memory next time, it will re-load clazz.detach () through javassist; return byteCode } catch (Exception ex) {ex.printStackTrace ();}} / / if null is returned, the bytecode will not be modified return null;}}

The following steps are the same as before, and the run will find that the logic of the add function has been replaced.

Dynamic mount

Dynamic mount is the dynamic addition of agent during the running of the application. The technical principle is to communicate with the target process through socket and send load instructions to mount the specified jar file in the target process. The function of agent execution is exactly the same as static overload. In the process of implementation, there are several differences. First of all, the entry function name is different, and the name of the dynamically mounted function is agentmain. Similar to premain, there are two formats. But the one with Instrumentation is usually used. As shown in the following example

Public class AgentMain {public static void agentmain (String agentArgs, Instrumentation instrumentation) throws UnmodifiableClassException {instrumentation.addTransformer (new MyClassTransformer (), true); instrumentation.retransformClasses (com.huawei.Test.class) } static class MyClassTransformer implements ClassFileTransformer {@ Override public byte [] transform (final ClassLoader loader, final String className, final Class classBeingRedefined, final ProtectionDomain protectionDomain) Final byte [] classfileBuffer) {/ / if the currently loaded class is the test class we wrote Enter the modification. If ("com/huawei/App" .equals (className)) {try {/ / get the CtClass object final ClassPool classPool = ClassPool.getDefault () from ClassPool; final CtClass clazz = classPool.get ("com.huawei.App") / / print all member functions in the App class CtMethod [] methodList = clazz.getDeclaredMethods (); for (CtMethod method: methodList) {System.out.println ("premain method:" + method.getName ()) } / / get the add function and replace it. $1 represents the first input parameter of the function CtMethod convertToAbbr = clazz.getDeclaredMethod ("add"); String methodBody = "{return $1 + $2 + 11;}"; convertToAbbr.setBody (methodBody) / / the bytecode is returned, and the detachCtClass object byte [] byteCode = clazz.toBytecode (); / / detach means to remove the Date object that has been loaded by javassist in memory, and if it is not found in memory next time, it will re-load clazz.detach () through javassist; return byteCode } catch (Exception ex) {ex.printStackTrace ();}} / / if null is returned, the bytecode will not be modified return null;}

The function is the same as static loading. It should be noted that after Instrumentation adds transformer, the retransformClasses function is called. This is because transformer is called only when the Java virtual machine loads class. If you are loading dynamically, the class file that needs to be monitored may have been loaded. So you need to call retransformClasses to reload.

Another difference is that the MANIFEST.MF file needs to add Agent-Class, as shown below

Can-Redefine-Classes: trueCan-Retransform-Classes: truePremain-Class: com.huawei.PreMainAgent-Class: com.huawei.AgentMain

The last difference is that the loading method is different. Dynamic mount requires a load script to be written. As shown below, in this script, you first iterate through all the java processes and identify the processes that need to be monitored by starting the class name. Get the VirtualMachine instance through the process id and load the jar file of agentmain.

Import com.sun.tools.attach.*;import java.io.IOException;import java.util.List; public class TestAgentMain {public static void main (String [] args) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {/ / get all running virtual machines System.out.println ("running JVM start") in the current system; List list = VirtualMachine.list () For (VirtualMachineDescriptor vmd: list) {System.out.println (vmd.displayName ()); String aim = "com.huawei.App"; if (vmd.displayName (). EndsWith (aim)) {System.out.println (String.format ("find% s, process id% s", vmd.displayName (), vmd.id () VirtualMachine virtualMachine = VirtualMachine.attach (vmd.id ()); virtualMachine.loadAgent ("/ root/Java-Agent-Project-Path/target/JavaAgentTest-1.0-SNAPSHOT.jar"); virtualMachine.detach ();} Scala program monitoring

Scala is compatible with Java, so it is feasible to use java-agent to monitor scala applications. But there are still some problems to pay attention to. The first point is that program replacement works only for class, not for object. The second problem is that in dynamic replacement, the program is compiled into bytecode and then replaced. Java-agent uses the compilation rules of java, so the replacement program should use the language rules of java, otherwise there will be compilation errors. For example, if you use System.out.println to output parameter information in the example, a compilation error will occur if you use scala's println.

Thank you for your reading, the above is the content of "how to use java-agent", after the study of this article, I believe you have a deeper understanding of how to use java-agent, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report