问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

Java实现热加载的三种方式

发布网友 发布时间:2024-10-01 17:30

我来回答

1个回答

热心网友 时间:2024-10-17 22:32

基于java agent方式

新建一个maven工程

publicstaticvoidpremain(StringagentArgs,Instrumentationinst){Trace.info("HotAgent-premain-start");Trace.info("isReadefineClassesSupported:"+inst.isRedefineClassesSupported());newReloader(inst).reload();}publicstaticvoidagentmain(StringagentArgs,Instrumentationinst){premain(agentArgs,inst);}

再pom中增加一下

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>3.0.2</version><configuration><archive><manifestEntries><Can-Redefine-Classes>true</Can-Redefine-Classes><Premain-Class>com.reload.HotAgent</Premain-Class><Agent-Class>com.reload.HotAgent</Agent-Class></manifestEntries></archive></configuration></plugin></plugins></build>

核心代码如下\ 主要是利用JDK中Instrument的redefine方法去重定义class,去重新加载了Class.

for(ClassDefinitionWraprWrap:redefineClassWrap){Trace.info("redefineclass"+rWrap.getClassname());inst.redefineClasses(newClassDefinition(rWrap.getCls(),rWrap.getBs()));result.appendMsg("热加载类:?"+rWrap.getClassname()+"成功");}基于Classloader方式

热加载就是利用新建自定义Classloader去加载Class,让后利用Thread的contexClassloader去替换老的classloader加载的class,这样就能实现 热加载。以下是demo的代码:

TestClassLoadertestClassLoader=newTestClassLoader();System.out.println("parentclassloader:"+testClassLoader.getParent());Thread.currentThread().setContextClassLoader(testClassLoader);Classclazz=testClassLoader.loadClass("com.plugin.AutoReload");System.out.println(clazz.hashCode());System.out.println(clazz.getClassLoader());System.out.println(testClassLoader);TestClassLoadernewClassLoader=newTestClassLoader(Thread.currentThread().getContextClassLoader());Thread.currentThread().setContextClassLoader(newClassLoader);System.out.println(newClassLoader);Classclazz1=newClassLoader.loadClass("com.plugin.AutoReload");System.out.println(clazz1.hashCode());System.out.println(clazz1.getClassLoader());

自定义Classloader的示例代码:

publicclassTestClassLoaderextendsClassLoader{publicTestClassLoader(ClassLoaderparent){super(parent);}publicTestClassLoader(){}@OverridepublicClass<?>loadClass(Stringname)throwsClassNotFoundException{Classc=null;synchronized(getClassLoadingLock(name)){if(c==null){try{ClassLoaderparent=getParent();if(parent!=null){c=parent.loadClass(name);}}catch(ClassNotFoundExceptione){//ClassNotFoundExceptionthrownifclassnotfound//fromthenon-nullparentclassloader}}if(c!=null){returnc;}byte[]bytes=loadclassData(name);System.out.println("====="+name);if(bytes!=null){returndefineClass(name,bytes,0,bytes.length);}}thrownewClassNotFoundException(name);}privatebyte[]loadclassData(StringclassName){returngetContent(getResourceStream(className));}privateInputStreamgetResourceStream(StringtoLoadClassName){System.out.println("loadclassname"+toLoadClassName);try{JarFilejar=newJarFile(Constants.WATCH_PACKAGE+File.separator+"plugin-1.0-SNAPSHOT.jar");//包名Enumeration<JarEntry>entry=jar.entries();JarEntryjarEntry;Stringname;StringclassName;Classclazz=null;while(entry.hasMoreElements()){jarEntry=entry.nextElement();name=jarEntry.getName();if(name.startsWith("/")){name=name.substring(1);}if(jarEntry.isDirectory()||!name.endsWith(".class")){continue;}//去掉.classclassName=name.substring(0,name.length()-6).replace("/",".");System.out.println(className);if(className.equals(toLoadClassName)){returnjar.getInputStream(jarEntry);}}}catch(IOExceptione){e.printStackTrace();}returnnull;}publicbyte[]getContent(InputStreaminputStream){//读取Class文件呢ByteArrayOutputStreambyteSt=newByteArrayOutputStream();//写入byteStreamintlen=0;try(InputStreamin=inputStream){while((len=in.read())!=-1){byteSt.write(len);}}catch(IOExceptione){e.printStackTrace();}//转换为数组returnbyteSt.toByteArray();}}基于groovy方式

基于Groovy方式,就是利用GroovyClassLoader的重新加载脚本,重新生成一个Class,GroovyClassLoader每次调用parseClass都是新城一个新的Class,这样就能实现Class的热加载.

StringscriptContent="packagecom.reload\n"+"\n"+"importorg.springframework.beans.factory.annotation.Autowired\n"+"\n"+"classHello{\n"+"\n"+"@Autowired\n"+"HelloServiceservice;\n"+"\n"+"HelloServicegetService(){\n"+"returnservice\n"+"}\n"+"\n"+"defrun(){\n"+"print(service.hello())\n"+"}\n"+"}";GroovyClassLoadergroovyClassLoader=newGroovyClassLoader();Classclazz=null;for(inti=0;i<3;i++){clazz=groovyClassLoader.parseClass(scriptContent);System.out.println(clazz.hashCode());}AnnotationConfigApplicationContextannotationConfigApplicationContext=newAnnotationConfigApplicationContext("com.reload");BeanDefinitionBuilderbeanDefinitionBuilder=BeanDefinitionBuilder.genericBeanDefinition(clazz);BeanDefinitionbeanDefinition=beanDefinitionBuilder.getRawBeanDefinition();((DefaultListableBeanFactory)annotationConfigApplicationContext.getBeanFactory()).registerBeanDefinition("hello",beanDefinition);//annotationConfigApplicationContext.getAutowireCapableBeanFactory().applyBeanPostProcessorsAfterInitialization(beanDefinition,"hello");GroovyObjectobject=(GroovyObject)annotationConfigApplicationContext.getBean("hello");object.invokeMethod("run",null);总结

本文主要介绍了三种实现JAVA中Class的热加载的三种方式:

基于java agent方式,只能实现class的增加、修改、删除方法和属性等,不能实现Class的新增,

基于Classloader方式, 可以实现class的增加、修改、删除方法和属性等,可以实现Class的新增,

基于Groovy方式, 可以实现class的增加、修改、删除方法和属性等,可以实现Class的新增,

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
草青青,青青草,草上接谢珍珠宝,怕日晒怕风摇,摇看珍珠得起早 谜底是... 一加9R要不要升级ColorOS 13正式版 一加9pro怎么coloros12一加9pro升级coloros12的方法 coloros12支持哪些一加机型?coloros12支持一加机型介绍 一加9pro如何coloros12?一加9pro升级coloros12的方法 一加9pro升级coloros12拍照改善吗 我是一个高中生,职教的,我们班上有5个女生,我喜欢有一个,但追她又有... 自动挡d挡旁边的 -是什么意思? 自动挡位上的加减是什么意思? 宣传这个职位是干什么的 一种简单的热部署方式结合动态编译实现java文件热替换 “烧心”、“胃部隐隐作病”等症状,是因为胃酸过多还是胃酸不足... 科鲁泽和科沃兹的区别 滑县地方特产 华为P10WLAN打不开/无法关闭 薛凯琪个人资料? 薛凯琪早年经历 薛凯琪演艺经历 大型工厂改变用洗地机的理由是什么? 外貌一般的女生怎么变好看? 外貌一般的人怎么快速变好看? 外貌一般的人怎么变好看? 显卡在我电脑的什么位子啊? 外貌一般的人如何逆袭变美? 这段时间孩子耳朵老是流黄水,还发臭,都影响他学习了,趁他放寒假想... ai软件里的置入和直接打开有什么不同ai软件里的置入和直接打开有什么不... ...的耳鼻喉医院是哪里?想看神经性耳鸣福州鼓楼医院耳鼻喉科看的好吗... 四大耳机品牌推荐 微信改名了别人能看到吗 请问亚飞除了9月27日来了后什么时候再还来广饶 ...说一个java语法问题,看了一下jasper.compiler.JDTCompiler类中的问题... 有谁知道阿里旺旺买家版与卖家版有什么区别,谢谢告知谢谢了,大神帮忙啊... 新买的小绵羊转绿灯了还要充多久 配电箱时控设置由电脑调整 淘宝 买家和卖家 使用的阿里旺旺 是一个版本的么 公园配电箱定的时间不到就亮了怎么回事 为什么配电箱内的漏电保护器在时控启动时总会有不同位置的开关跳闸,但 ... vivo手机的安全模式在哪里关闭 电视摁错了一个键不出人怎么办?我先嗯红的,在摁橙的 什么叫目标养老基金 养老目标基金频现清盘什么意思 新中国参加的历届奥运会分别都得过多少奖牌? 中国在奥运会上得了多少金牌 哪家快递公司邢台市贾村送货上门啊? ...哪一年发生的什么属性,大兴安岭火灾发生在哪一年_百度... 中通速递是不是分汽运和空运啊 学会使用数据分析的必备工具——EXCEL第二弹 求好看的古代泰剧,最好结局和 ...水反应生成硫酸锰,硫酸钾和硫酸 5SO2+2KMnO4+2H2O=K2SO4+2MnSO4+2... 二氧化硫和酸性高猛酸钾反应的产物是什么?拜托了各位 谢谢