Nothing to do but try the hot fixes in Java. The main principle is to dynamically load the class file in the form of references to Java classes that use dynamic mount to implement bugs in Java and to dynamically replace the target process
Two articles in the principle and practice of the detailed explanation, here to do a case of collation and the problems encountered and the two articles in some of the notes did not mention to carry out a note
preparation of the replaced class
First write a class libutil to be replaced, inside only a static method printstring, print a word
public class Libutil {public
static void Printstring (string s) {
System.out.println (' This is a bug String : "+s);
}
}
Then the test class needs to do the following
1. Print process number to facilitate hot fix new virtual machine attach to this process
2. Keep Calling the method of the class to be replaced so that we can see clearly the effect of the heat fix
The test classes are as follows:
Import Java.lang.management.ManagementFactory; public class Testhotswap { public static void Main (string[] args) { tes
Tstatic t= (Newtesthotswap ()). New Teststatic (); while (true) { try{
Thread.Sleep (5000); String name =
Managementfactory.getruntimemxbean (). GetName ();
System.out.println (name); // get pid
String pid = name.split ("@") [0];
System.out.println ("Pid is:" + Pid); T. print (); } catch ( Interruptedexception e) {} } } class teststatic{ & nbsp; public void print () { libutil.printstring ("Did U")
Miss me? "); } }}
preparation of hot fixes
Next we need to do three things:
1. Write a process to start a virtual machine and attach to the process that has been launched
2. Write a repair class to cover the problematic class
3. Write a proxy class, through the proxy class interface to achieve thermal repair, where this proxy class is to be packaged into a jar file form
The first is to write a fix class, which needs to be exactly the same as the original class in the package name, class name, modifier, otherwise the exception of ClassName T match will be generated during the classredefine process.
The code is as follows:
public class Libutil {public
static void Printstring (String s) {
System.out.println (' This is a fixed stri NG: "+s);
}
}
Then write the proxy class, which requires special attention to the following points:
1. The agent Main method must contain static
2. The following two lines must be included in the MANIFEST.MF file after the jar pack:
L Agent Class:agent-class:testhotswapdebug.debugjar
L Can-redefine-classes:true
The Agent class specifies the package name Class name of the proxy class
The Can Redefineclass property allows the package to be redefine on the loaded class
Import Java.io.ByteArrayOutputStream;
Import Java.io.FileInputStream;
Import Java.io.InputStream;
Import java.lang.instrument.ClassDefinition;
Import java.lang.instrument.Instrumentation; public class Debugjar { public static void Agentmain (String arg, Instrumentation inst) &NBSP;&NBSP;&NB sp; throws Exception { / /Only if header utility are on the classpath; Otherwise, /A class can is found within any classloader by iterating &NBSP;&N bsp; //Over the return value ofinstrumentation::getallloadedclasses //need to make a jar package and modify MANIFEST.MF add a row to specify the Agent Class:agent-class:testhotswapdebug.debugjar & nbsp; //Additional line: can-redefine-classes:true class<?> libutil =
Class.forName ("Processwithbug.libutil"); &NBSP;&Nbsp; //Copy the contents of Typo.fix into Abyte array
bytearrayoutputstream output = new Bytearrayoutputstream ();
InputStream Input=null; try { Input =new fileinputstream ("c:\\users\\administrator\\workspace\\testhotswapdebug\\bin\\processwithbug\\ Libutil.class ");//Package name class names should be consistent with the original
byte[] buffer = new byte[1024];
int length;
while (length = input.read (buffer)!=-1) { output.write (Buffer,
0, length); } }catch (Exception e) { if (input==null) System.out.println ("Class
Input is null "); Else
E.printstacktrace (); } //Apply the redefinition inst.redefineclasses (
New Classdefinition (Libutil, Output.tobytearray ())); } }
Next is a class that is used to attach to an existing process, with the following caveats:
1. Need to introduce Tools.jar in the project, this jar package is under the JDK's Lib folder, but the General IDE's running environment is JRE, so it needs to be added into the environment variable specifically
2. The need for dynamic loading of Attach.dll, the same attach.dll in a JDK bin directory, need to copy to the running directory, forget where the specific, you can search in the JDK directory, find later put under Jre/bin can be
Import Java.io.File;
Import Com.sun.tools.attach.VirtualMachine;
Public Classtestfixbug {
static
{
system.loadlibrary ("Attach");
Need to place Attach.dll under Java.library.path
} public
static void Main (string[] args) {
String ProcessID = "17244" //need to be modified to the PID
String jarfilename = "Fixbug.jar" for the process to be repaired;//a jar package name
file F=new file (jarfilename)
with the Agentmain fix class; System.out.println (F.getabsolutepath ());
Virtualmachine Virtualmachine;
try {
virtualmachine =virtualmachine.attach (ProcessID);
Virtualmachine.loadagent (Jarfilename, "world!");
Virtualmachine.detach ();
} catch (Exception e) {
e.printstacktrace ();}}}
Run Results
To run the test process for the class to be replaced first
11368@SKY-20150127GHW
Pid is:11368
Run the Attach process:
11368@SKY-20150127GHW
Pid is:11368
thisis a bug string:did u miss me?
11368@SKY-20150127GHW
Pid is:11368
thisis a bug string:did u miss me?
11368@SKY-20150127GHW
Pid is:11368
thisis a fixed string:did u miss me?
11368@SKY-20150127GHW
Pid is:11368 This is
a fixedstring:did u miss me?
some strange little phenomenon.
When the static method is invoked directly in main, it cannot be thermally repaired, and redefine success without effect. Guess is that the static method called in the static block is fixed at compile time and cannot be affected by a dynamically redefined method