首页>>后端>>java->Java实现热加载的三种方式

Java实现热加载的三种方式

时间:2023-12-05 本站 点击:0

基于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的新增,


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/java/12169.html