热加载新类

back_recharge
zhangshanxue 2019-10-09 16:51:49 +08:00
parent f47b80ea14
commit f45b6d4e83
1 changed files with 94 additions and 22 deletions

View File

@ -3,8 +3,10 @@ package com.ljsd.jieling.hotfix;
import java.io.*;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;
public class JavaAgent {
private static final ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
@ -39,59 +41,129 @@ public class JavaAgent {
return dateString;
}
private static void writeLog(Exception e){
private static void writeLog(Exception e) {
try {
String fname = "../logs/" + getStrDateYMD() + "_" + logFileName;
File file = new File(fname);
OutputStream fos=new FileOutputStream(file, true);
OutputStream fos = new FileOutputStream(file, true);
PrintStream out = new PrintStream(fos);
writeLog(e.getMessage());
e.printStackTrace(out);
out.close();
} catch(Exception e1){
} catch (Exception e1) {
e.printStackTrace();
e1.printStackTrace();
}
}
private static void writeLog(String line){
private static void writeLog(String line) {
try {
String fname = "../logs/" + getStrDateYMD() + "_" + logFileName;
File file = new File(fname);
OutputStream fos=new FileOutputStream(file, true);
OutputStream fos = new FileOutputStream(file, true);
PrintStream out = new PrintStream(fos);
line = "[" + getStrDateYMDHMS() + "][" + Thread.currentThread().getId() + "]:" + line + "\n";
System.out.print(line);
out.print(line);
out.close();
} catch(Exception e){
} catch (Exception e) {
e.printStackTrace();
}
}
//该方法支持在JVM 启动后再启动代理对应清单的Agent-Class:属性
public static void agentmain(String args,Instrumentation inst){
try{
public static void agentmain(String args, Instrumentation inst) {
try {
writeLog("argsxxxxxxxxxx=:[" + args + "]");
writeLog("argsxxxxxxxxxxyyy=:[" + JavaAgent.class.getResource("").getPath() + "]");
File f = new File(args);
byte[] targetClassFile = new byte[(int)f.length()];
String[] paths = args.split("#");
File f = new File(paths[0]);
byte[] targetClassFile = new byte[(int) f.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(f));
dis.readFully(targetClassFile);
dis.close();
DynamicClassLoader myLoader = new DynamicClassLoader();
Class targetClazz = myLoader.findClass(targetClassFile);
writeLog("class namexxxxx is:["+targetClazz.getName() + "]");
writeLog("class path is:["+targetClazz.getResource("").getPath() + "]");
Class<?> clz = Class.forName(targetClazz.getName());
writeLog("clz-->Class.forName:(\""+targetClazz.getName() + "\")");
Class<?> loads = null;
try {
loads = Class.forName(paths[1]);
} catch (Exception var18) {
}
if (null != loads ) {
try {
ClassDefinition clazzDef = new ClassDefinition(loads, targetClassFile);
inst.redefineClasses(clazzDef);
writeLog("热加载(旧)"+loads.getName()+"成功"+"\r\n");
}catch (Exception oldVarErr){
writeLog("热加载(旧)"+loads.getName()+"失败"+"\r\n"+oldVarErr);
}
}else {
ClassDefinition clazzDef = new ClassDefinition(clz, targetClassFile);
writeLog("ClassDefinition");
JavaAgent agent = new JavaAgent();
if(!defineNewClass(paths[1],agent.getClass().getClassLoader(),targetClassFile)){
writeLog("热加载(新类)"+paths[0]+"失败"+"\r\n");
}
inst.redefineClasses(clazzDef);
writeLog("redefineClasses "+args+" finish!");
Class cls=null;
try {
cls = Class.forName(paths[1]);
} catch (ClassNotFoundException newVarErr) {
writeLog("热加载(新类)"+paths[0]+"失败—ClassNotFoundException"+"\r\n"+newVarErr);
}
}catch(Exception e){
writeLog(e);
if (null == cls) {
writeLog("热加载(新类)"+paths[0]+"失败—null"+"\r\n");
}
writeLog("热加载(新类)"+paths[0]+"成功"+"\r\n");
}
// DynamicClassLoader myLoader = new DynamicClassLoader();
// Class targetClazz = myLoader.findClass(targetClassFile);
// writeLog("class namexxxxx is:[" + targetClazz.getName() + "]");
// writeLog("class path is:[" + targetClazz.getResource("").getPath() + "]");
// Class<?> clz = Class.forName(targetClazz.getName());
// writeLog("clz-->Class.forName:(\"" + targetClazz.getName() + "\")");
//
// String names2= targetClazz.getName();
//
//
//
// writeLog("redefineClasses " + paths[0] + " finish!");
} catch (Exception e) {
writeLog("热加载"+"失败"+"\r\n"+e.toString());
}
}
private static boolean defineNewClass(String classname, ClassLoader classLoader, byte[] bs) {
Method method = getMethod(classLoader.getClass(), "defineClass", new Class[]{String.class, byte[].class, Integer.TYPE, Integer.TYPE});
if (method == null) {
return false;
} else {
method.setAccessible(true);
try {
method.invoke(classLoader, classname, bs, 0, bs.length);
return true;
} catch (Throwable var6) {
return false;
}
}
}
public static Method getMethod(Class<?> cls, String methodName, Class... classes) {
Method method = null;
Class clazz = cls;
while(clazz != Object.class) {
try {
method = clazz.getDeclaredMethod(methodName, classes);
break;
} catch (NoSuchMethodException var6) {
clazz = clazz.getSuperclass();
}
}
return method;
}
}