public class JavaAgent {
public static final Logger logger = LoggerFactory.getLogger(JavaAgent.class);
private static String classesPath;
private static String jarPath;
private static VirtualMachine vm;
private static String pid;
static {
classesPath = JavaAgent.class.getClassLoader().getResource("").getPath();
logger.error("java agent:classpath:{}", classesPath);
jarPath = getJarPath();
logger.error("java agent:jarPath:{}", jarPath);
// 当前进程pid
String name = ManagementFactory.getRuntimeMXBean().getName();
pid = name.split(];
logger.error("当前进程pid:{}", pid);
}
/**
* 获取jar包路径
* @return
*/
public static String getJarPath() {
// StringUtils是jar文件内容
URL url = StringUtils.class.getProtectionDomain().getCodeSource().getLocation();
String filePath = null;
try {
filePath = URLDecoder.decode(url.getPath(), "utf-8");// 转化为utf-8编码
} catch (Exception e) {
e.printStackTrace();
}
if (filePath.endsWith(".jar")) {// 可执行jar包运行的结果里包含".jar"
// 截取路径中的jar包名
filePath = filePath.substring(, filePath.lastIndexOf();
}
File file = new File(filePath);
filePath = file.getAbsolutePath();//得到windows下的正确路径
return filePath;
}
private static void init() throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {
// 虚拟机加载
vm = VirtualMachine.attach(pid);
vm.loadAgent(jarPath + "/javaagent.jar");
Instrumentation instrumentation = JavaDynAgent.getInstrumentation();
Preconditions.checkNotNull(instrumentation, "initInstrumentation must not be null");
}
private static void destroy() throws IOException {
if (vm != null) {
vm.detach();
}
}
/**
* 重新加载类
*
* @param classArr
* @throws Exception
*/
public static void javaAgent(String root, String[] classArr) throws ClassNotFoundException, IOException, UnmodifiableClassException, AttachNotSupportedException, AgentLoadException, AgentInitializationException {
init();
try {
// 1.整理需要重定义的类
List classDefList = new ArrayList();
for (String className : classArr) {
Class> c = Class.forName(className);
String classPath = (StringUtils.isNotBlank(root) ? root : classesPath) + className.replace(".", "/") + ".class";
logger.error("class redefined:" + classPath);
byte[] bytesFromFile = Files.toByteArray(new File(classPath));
ClassDefinition classDefinition = new ClassDefinition(c, bytesFromFile);
classDefList.add(classDefinition);
}
// 2.redefine
JavaDynAgent.getInstrumentation().redefineClasses(classDefList.toArray(new ClassDefinition[classDefList.size()]));
} finally {
destroy();
}
}
public static void main(String[] args) throws Exception {
PortUtil.test();
javaAgent(null, new String[] {"com.agileeagle.webgame.framework.util.PortUtil"});
PortUtil.test();
}
}