When debugging locally, the code can be compiled and updated in real-time, and it can be continuously updated on the fly to dynamically update the class, known as Java Thermal deployment.
two ways of JDK proxy:The 1.premain approach is the proxy method that Java SE5 starts with, but it must specify the proxy jar on the command line, and the proxy class muststart before the main method, it requires the developer to confirm the agent's processing logic and parameter contents before the application is started, and so on, 2.agentmain is JavaSE6 to start providing, it can be in the applicationafter the VM startsHow to add agents dynamically
agentmain Application Scenario:For example, the normal production environment, generally does not open the agent function, but in the event of a problem, we do not want to stop the application can dynamically modify some of the behavior of some classes to help troubleshoot problems, this is not determined before the application started with Permain similar, agent method also need to provide an agent Jar, and this jar needs to meet the [viewable attachment jar file]:1. In manifest, the Agent-class attribute is specified, and the value is the proxy class full path 2. The proxy class needs to provide public static void Agentmain (String args , Instrumentation inst) or public static void Agentmain (String args) method. And both exist at the same time before the former is preferred. Args is consistent with inst and Premain.
so how to change the class dynamically in the case of non-stop service?? The implementation code is as follows: Java Code code Dynamic Change Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
|
Publicclassjavaagent {
PublicStaticFinalLogger Logger = Loggerfactory.getlogger (javaagent.class);
PrivateStaticStringClassespath; PrivateStatic StringJarpath; PrivateStaticVirtualmachine VMS; PrivateStaticStringpid
Static{ Classespath = javaagent.class. getClassLoader (). GetResource (""). GetPath (); Logger.error ("Java agent:classpath:{}", Classespath); Jarpath = Getjarpath (); Logger.error ("Java agent:jarpath:{}", Jarpath);
//Current process PID StringName = Managementfactory.getruntimemxbean (). GetName (); PID = Name.split ("@")[0]; Logger.error ("Current Process pid:{}", PID); }
/** * Get the JAR package path * @return */ PublicStaticStringGetjarpath () { //StringUtils is a jar file content URL url = stringutils.class. Getprotectiondomain (). Getcodesource (). GetLocation (); StringFilePath = null; Try{ FilePath = Urldecoder.decode (Url.getpath (),"Utf-8");Convert to UTF-8 encoding }Catch(Exception e) { E.printstacktrace (); } if(Filepath.endswith (". Jar")) {//Executable jar package runs with ". Jar" in the result //The jar package name in the Intercept path FilePath = filepath.substring (0, Filepath.lastindexof ("/") +1); }
File File =NewFile (FilePath);
FilePath = File.getabsolutepath ();//Get the correct path under Windows returnFilePath; }
PrivateStaticvoidInit ()throwsIOException, Attachnotsupportedexception, Agentloadexception, agentinitializationexception { //virtual machine load VM = Virtualmachine.attach (PID); Vm.loadagent (Jarpath +"/javaagent.jar");
Instrumentation instrumentation = javadynagent.getinstrumentation (); Preconditions.checknotnull (instrumentation,"Initinstrumentation must not being null"); }
PrivateStaticvoidDestroy ()throwsIOException { if(VM! = null) { Vm.detach (); } }
/** * Reload Class * * @param Classarr * @throws Exception */ PublicStatic voidJavaagent (StringRootString[] Classarr)throwsClassNotFoundException, IOException, Unmodifiableclassexception, Attachnotsupportedexception, AgentLoadException, agentinitializationexception { Init ();
Try{ //1. Organize classes that need to be redefined List<classdefinition> classdeflist =NewArraylist<classdefinition> (); for(StringClassname:classarr) { class<?> C = class.forname (ClassName); StringClassPath = (Stringutils.isnotblank (root)? root:classespath) + Classname.replace (".","/") +". Class"; Logger.error ("class redefined:"+ ClassPath); byte[] Bytesfromfile = Files.tobytearray (NewFile (ClassPath)); Classdefinition classdefinition =NewClassdefinition (c, bytesfromfile); Classdeflist.add (classdefinition); } //2.redefine Javadynagent.getinstrumentation (). Redefineclasses (Classdeflist.toarray (NewClassdefinition[classdeflist.size ()]); }finally{ Destroy (); } }
PublicStaticvoidMainString[] args)throwsException { Portutil.test ();
Javaagent (NULL,NewString[] {"Com.agileeagle.webgame.framework.util.PortUtil"});
Portutil.test (); } } |
Java CodeInstrumentationHow do I get it?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21st 22 23 24 |
|
Publicclassjavadynagent { PrivateStaticinstrumentation instrumentation; PrivateStaticObject LockObject =NewObject ();
PublicJavadynagent () { }
Public StaticvoidAgentmain (Stringargs, Instrumentation inst) { Object var2 = lockobject; synchronized(LockObject) { if(instrumentation = = null) { instrumentation = Inst; System.out.println ("0->"+ inst); }Else{ System.out.println ("1->"+ inst); }
} }
PublicStaticInstrumentation getinstrumentation () { returninstrumentation; } } |
The implementation principle is:1. Bind the PID to get the virtual machine object, and then load the agent jar package through the virtual machine so that it is called to theAgentmain, getInstrumentation2. Based onInstrumentationInterfaces can implement the broker mechanism of the JDK, enabling dynamic redefinition of the class. Note: Com.sun.tools.attach.VirtualmachineThe jar package isTools.jar in the JDK under Lib, so the jar is referenced in the project, and because it involves the underlying virtual machine, Windows and Linux machines have different jars.the whole process is:1. Jdk/lib/tools.jar is referenced in the project, otherwise the Virtualmachine Class 2 cannot be used. Javaagent.jar is referenced in the project, it provides Agentmain interface 3. Code implementation dynamically add JDK Proxy
Java code hot deployment, online non-stop service dynamic update