当前位置: 首页 > news >正文

SpringBoot自定义类加载器

讲解如何获取springBoot classLoader和如何往spring boot classLoader 添加包

获取spring boot classLoader

 /*** SpringBoot打包模式下是SpringBoot的类加载器* @return*/public static ClassLoader genClassLoader(){if (!SystemInfo.INSTANCE.isStandalone()) {return null;}AgentLogger.info("[SF Agent] Use springboot classloader.");try {// 检测是否SpringBoot打包方式Class launcherClass = Class.forName(STANDALONE_CLASS);if (launcherClass != null) {String jarfilePath = ClassUtils.getClassFilePath(launcherClass);if (null == jarfilePath) {return null;}// 获取Manifest,并且获取Main-Class,可能是JarLauncher或者是WarLauncherClass jarFileArchiveClass = Class.forName("org.springframework.boot.loader.archive.JarFileArchive");Object jarFileArchiveObj = jarFileArchiveClass.getDeclaredConstructor(File.class).newInstance(new File(jarfilePath));Method manifestMethod = jarFileArchiveClass.getDeclaredMethod("getManifest");Manifest manifest = (Manifest)manifestMethod.invoke(jarFileArchiveObj);String mainClass = manifest.getMainAttributes().getValue("Main-Class");// 反射调用Launcer,获取可以加载SpringBoot依赖的类加载器Class launcher = Class.forName(mainClass);Map<String, Method> methods = getClassLoadderMethod(launcher);Method classLoaderMethod = methods.get("classLoader");Method archivesMethod = methods.get("archive");if (null == classLoaderMethod || null == archivesMethod) {AgentLogger.error("No class loader found.");return null;}archivesMethod.setAccessible(true);classLoaderMethod.setAccessible(true);Object launcherObj = launcher.getDeclaredConstructor().newInstance();Object classPathArchives = archivesMethod.invoke(launcherObj);return (ClassLoader)classLoaderMethod.invoke(launcherObj, classPathArchives);}} catch (Exception e) {}return null;}

通过字节码增强往spring boot classLoader 添加包

public abstract class AbstractEnhanceModel {public abstract byte[] enhance(String className, byte[] source);}
import enhance.AbstractEnhanceModel;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;public class SpringBootEnhance extends AbstractEnhanceModel {public static final SpringBootEnhance INSTANCE = new SpringBootEnhance();private SpringBootEnhance(){}@Overridepublic byte[] enhance(String className, byte[] source) {ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);ClassReader classReader = new ClassReader(source);AgentJarEnhance agentInitEnhance = new AgentJarEnhance(classWriter);classReader.accept(agentInitEnhance, ClassReader.SKIP_DEBUG);return classWriter.toByteArray();}
}
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;import static org.objectweb.asm.Opcodes.*;public class AgentJarEnhance extends ClassVisitor {private ClassVisitor cv;public AgentJarEnhance(ClassVisitor classVisitor) {super(ASM4, classVisitor);this.cv = classVisitor;}@Overridepublic MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {// 新版接口转换为旧版接口if ("isPostProcessingClassPathArchives".equals(name)) {return null;}if ("postProcessClassPathArchives".equals(name)) {return null;}if ("genArchive".equals(name)) {return null;}return cv.visitMethod(access, name, descriptor, signature, exceptions);}@Overridepublic void visitEnd(){isPostProcessingClassPathArchives();postProcessClassPathArchives();cv.visitEnd();}private void isPostProcessingClassPathArchives(){MethodVisitor methodVisitor = cv.visitMethod(ACC_PUBLIC, "isPostProcessingClassPathArchives", "()Z", null, null);methodVisitor.visitCode();Label label0 = new Label();methodVisitor.visitLabel(label0);methodVisitor.visitLineNumber(14, label0);methodVisitor.visitInsn(ICONST_1);methodVisitor.visitInsn(IRETURN);Label label1 = new Label();methodVisitor.visitLabel(label1);methodVisitor.visitLocalVariable("this", "Lorg/springframework/boot/loader/JarLauncher;", null, label0, label1, 0);methodVisitor.visitMaxs(1, 1);methodVisitor.visitEnd();}private void postProcessClassPathArchives(){MethodVisitor methodVisitor = cv.visitMethod(ACC_PROTECTED, "postProcessClassPathArchives", "(Ljava/util/List;)V", "(Ljava/util/List<Lorg/springframework/boot/loader/archive/Archive;>;)V", new String[]{"java/lang/Exception"});methodVisitor.visitCode();Label label0 = new Label();methodVisitor.visitLabel(label0);methodVisitor.visitLineNumber(42, label0);methodVisitor.visitVarInsn(ALOAD, 1);methodVisitor.visitInsn(ICONST_0);methodVisitor.visitVarInsn(ALOAD, 0);methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/springframework/boot/loader/JarLauncher", "getArchive", "()Lorg/springframework/boot/loader/archive/Archive;", false);methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(ILjava/lang/Object;)V", true);Label label1 = new Label();methodVisitor.visitLabel(label1);methodVisitor.visitLineNumber(43, label1);// 往classLoader添加jar包methodVisitor.visitMethodInsn(INVOKESTATIC, "agent/config/SupportConfig", "getAll", "()Ljava/util/List;", false);methodVisitor.visitVarInsn(ASTORE, 2);Label label2 = new Label();methodVisitor.visitLabel(label2);methodVisitor.visitLineNumber(44, label2);methodVisitor.visitVarInsn(ALOAD, 2);methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "iterator", "()Ljava/util/Iterator;", true);methodVisitor.visitVarInsn(ASTORE, 3);Label label3 = new Label();methodVisitor.visitLabel(label3);methodVisitor.visitFrame(Opcodes.F_APPEND, 2, new Object[]{"java/util/List", "java/util/Iterator"}, 0, null);methodVisitor.visitVarInsn(ALOAD, 3);methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "hasNext", "()Z", true);Label label4 = new Label();methodVisitor.visitJumpInsn(IFEQ, label4);methodVisitor.visitVarInsn(ALOAD, 3);methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/util/Iterator", "next", "()Ljava/lang/Object;", true);methodVisitor.visitTypeInsn(CHECKCAST, "java/lang/String");methodVisitor.visitVarInsn(ASTORE, 4);Label label5 = new Label();methodVisitor.visitLabel(label5);methodVisitor.visitLineNumber(45, label5);methodVisitor.visitTypeInsn(NEW, "org/springframework/boot/loader/jar/JarFile");methodVisitor.visitInsn(DUP);methodVisitor.visitTypeInsn(NEW, "java/io/File");methodVisitor.visitInsn(DUP);methodVisitor.visitVarInsn(ALOAD, 4);methodVisitor.visitMethodInsn(INVOKESPECIAL, "java/io/File", "<init>", "(Ljava/lang/String;)V", false);methodVisitor.visitMethodInsn(INVOKESPECIAL, "org/springframework/boot/loader/jar/JarFile", "<init>", "(Ljava/io/File;)V", false);methodVisitor.visitVarInsn(ASTORE, 5);Label label6 = new Label();methodVisitor.visitLabel(label6);methodVisitor.visitLineNumber(46, label6);methodVisitor.visitVarInsn(ALOAD, 1);methodVisitor.visitTypeInsn(NEW, "org/springframework/boot/loader/archive/JarFileArchive");methodVisitor.visitInsn(DUP);methodVisitor.visitVarInsn(ALOAD, 5);methodVisitor.visitMethodInsn(INVOKESPECIAL, "org/springframework/boot/loader/archive/JarFileArchive", "<init>", "(Lorg/springframework/boot/loader/jar/JarFile;)V", false);methodVisitor.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "add", "(Ljava/lang/Object;)Z", true);methodVisitor.visitInsn(POP);Label label7 = new Label();methodVisitor.visitLabel(label7);methodVisitor.visitLineNumber(47, label7);methodVisitor.visitJumpInsn(GOTO, label3);methodVisitor.visitLabel(label4);methodVisitor.visitLineNumber(48, label4);methodVisitor.visitFrame(Opcodes.F_CHOP, 1, null, 0, null);methodVisitor.visitInsn(RETURN);Label label8 = new Label();methodVisitor.visitLabel(label8);methodVisitor.visitLocalVariable("jarFile", "Lorg/springframework/boot/loader/jar/JarFile;", null, label6, label7, 5);methodVisitor.visitLocalVariable("path", "Ljava/lang/String;", null, label5, label7, 4);methodVisitor.visitLocalVariable("this", "Lorg/springframework/boot/loader/JarLauncher;", null, label0, label8, 0);methodVisitor.visitLocalVariable("archives", "Ljava/util/List;", "Ljava/util/List<Lorg/springframework/boot/loader/archive/Archive;>;", label0, label8, 1);methodVisitor.visitLocalVariable("paths", "Ljava/util/List;", "Ljava/util/List<Ljava/lang/String;>;", label2, label8, 2);methodVisitor.visitMaxs(5, 6);methodVisitor.visitEnd();}
}
import java.util.ArrayList;
import java.util.List;public class SupportConfig {private static final String KEY = "Governance.SupportConfig";private static final String SPLIT = ";";public static void add(String support) {String value = System.getProperty(KEY);if (null == value || value.length() < 1) {value = support;}else {value = value + SPLIT + support;}System.setProperty(KEY, value);}public static List<String> getAll(){String value = System.getProperty(KEY);if (null == value || value.length() < 1) {return new ArrayList<>();}List<String> list = new ArrayList<>();String[] values = value.split(SPLIT);for(String row : values) {list.add(row);}return list;}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • linux查看网卡速度和pcie速度
  • 【Python零基础】while循环和用户输入
  • SPI驱动学习一(协议原理)
  • 硬件服务器操作系统的选择:Linux 还是 Windows?
  • 地理科学专业| 中国大学排行榜(2024年)
  • PgSQL HashAgg算法 | 第2期 | 版本12的spill溢出磁盘解秘
  • linux之ELK
  • [Hdp] lc552. 学生出勤记录 II(dp+递推+状态定义+状态转移+向前转移+好题)
  • Clichouse数据导出导入(数据迁移)
  • 重头开始嵌入式第二十三天(进程2)
  • Unity | 性能优化
  • 【分享】格力手机色界G0245D 刷REC、root、 救砖、第三方rom教程和资源
  • 论文辅导 | 基于改进灰色预测模型的港口物流需求预测研究
  • opencv图像基本操作
  • [MRCTF2020]套娃1
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • 【面试系列】之二:关于js原型
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • java取消线程实例
  • java小心机(3)| 浅析finalize()
  • Mithril.js 入门介绍
  • Node 版本管理
  • Phpstorm怎样批量删除空行?
  • Redux 中间件分析
  • 第十八天-企业应用架构模式-基本模式
  • - 概述 - 《设计模式(极简c++版)》
  • 欢迎参加第二届中国游戏开发者大会
  • 如何胜任知名企业的商业数据分析师?
  • 如何使用 JavaScript 解析 URL
  • 小程序测试方案初探
  • linux 淘宝开源监控工具tsar
  • MPAndroidChart 教程:Y轴 YAxis
  • 阿里云服务器如何修改远程端口?
  • 积累各种好的链接
  • ​【已解决】npm install​卡主不动的情况
  • # Panda3d 碰撞检测系统介绍
  • (20050108)又读《平凡的世界》
  • (java)关于Thread的挂起和恢复
  • (javaweb)Http协议
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (二)延时任务篇——通过redis的key监听,实现延迟任务实战
  • (十三)MipMap
  • (四)stm32之通信协议
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)人的集合论——移山之道
  • .net core 依赖注入的基本用发
  • .net MVC中使用angularJs刷新页面数据列表
  • .net 受管制代码
  • .NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • .NET项目中存在多个web.config文件时的加载顺序
  • .project文件
  • ::前边啥也没有