- 浏览: 469263 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (135)
- javascript (43)
- struts (3)
- webWork (0)
- hibernate (2)
- EJB (0)
- Spring (2)
- XML (2)
- Oracle (4)
- Mysql (0)
- C (0)
- C++ (0)
- 网络 (0)
- linux (4)
- java (28)
- 设计模式 (0)
- java 代理模式 (2)
- jsp&Servlet (2)
- Tomcat (5)
- 算法设计 (2)
- 操作技巧 (1)
- HTML (5)
- Ajax (2)
- JScript Deviations from ES3 (14)
- Eclipse (1)
- log4J (2)
- ant (1)
- HTTP (4)
- project (1)
- SqlServer (4)
- 数据仓库 (0)
最新评论
-
u012526168:
header的域名是大小写敏感的.http://stackov ...
HTTP 请求报头详解 -
junes_yu:
这样的方法有问题哦正确方法如下:document.onkeyd ...
javascript 屏蔽F5,BackSpace,IE的刷新,右键功能 -
xunke515:
第二个,如果要带顺序的话,new个treeset也可以吧.
两种方法删除ArrayList里重复元素 -
bangyulin:
java 潜拷贝和深拷贝 -
hecongqi:
谢谢,写得很好,学到知识了
浅谈Java代理机制
关键字: classloader 热部署
这两天一直在学习一些classloader的相关知识,看了一些文章,了解到classloader的作用之一就是实现热部署功能。于是就看了一个网络上的一个例子,然后自己实现了一个应用。虽然作出来了,但是说实话:不满意。因为在这个例子当中,只要热部署一次,就要重新new一个classloader,这样会引发什么问题我也不清楚,并且,classloader究竟实现了什么,以及一些底层的东西我还不是很了解,还要继续研究,目前的版本就是一个中间版本。以后还要优化,或者在我读完tomcat的classloader之后我在去仿照着写一个。
好了,下面介绍这个工程的构思、以及实现方式,设计思想:首先来说:这个工程至少需要是需要2个线程,一个是类似tomcat的服务线程,另外一个就是检测线程,检测变化,重新加载Class对象。我猜tomcat是采取了检测类,检测加载了的类文件变化。我没有那么实现,因为这种实现方式相对复杂,并且我的想集中解决热部署问题,而不是如何实现监控文件,所以我就采取了相对简单的方式:socket通知方式。也就是,在我重新编译一个class之后,利用socket通知检测线程,监测监测在监测到socket命令之后会自动的加载。
该类会自动加载d:\hotdeploys下的类文件.
下面这个就是测试类
Java代码
main线程主要是服务线程,通过调用startService()不停的通过system.out来打印。支线程负责监听端口(9090),当有连接信号后就重新加载类。
服务接口很简单,如下
总结:所有的customerClassLoader都要加载与之相关的类(比如:父类、包含的类)。如果你需要override loadclass(string, boolean)绕过findLoadedClass()检测,只能引发java.lang.LinkageError:duplicate class definition for name: "com/cxz/jiangyou/Sample"因此,比较通用的重新加载方式应该就是new一个用户定义的classloader
这两天一直在学习一些classloader的相关知识,看了一些文章,了解到classloader的作用之一就是实现热部署功能。于是就看了一个网络上的一个例子,然后自己实现了一个应用。虽然作出来了,但是说实话:不满意。因为在这个例子当中,只要热部署一次,就要重新new一个classloader,这样会引发什么问题我也不清楚,并且,classloader究竟实现了什么,以及一些底层的东西我还不是很了解,还要继续研究,目前的版本就是一个中间版本。以后还要优化,或者在我读完tomcat的classloader之后我在去仿照着写一个。
好了,下面介绍这个工程的构思、以及实现方式,设计思想:首先来说:这个工程至少需要是需要2个线程,一个是类似tomcat的服务线程,另外一个就是检测线程,检测变化,重新加载Class对象。我猜tomcat是采取了检测类,检测加载了的类文件变化。我没有那么实现,因为这种实现方式相对复杂,并且我的想集中解决热部署问题,而不是如何实现监控文件,所以我就采取了相对简单的方式:socket通知方式。也就是,在我重新编译一个class之后,利用socket通知检测线程,监测监测在监测到socket命令之后会自动的加载。
Java代码 package com.cxz.classloader; import com.cxz.jiangyou.Say; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; /** * This classloader is like a template * which includes pre-loadClass and after-loadClass * @author Bernard * */ public class ComplexClassLoader extends ClassLoader { public ComplexClassLoader() { } public ComplexClassLoader(String defaultTargetDir) { this.defaultTargetDir = defaultTargetDir; } private String defaultTargetDir = "D:\\hotdeploys\\"; public Class<?> findClass(String className) throws ClassNotFoundException { byte[] classBytes = null; try { classBytes = loadByteCode(className); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return super.defineClass(className, classBytes, 0, classBytes.length); } private byte[] loadByteCode(String className) throws IOException { int ch = 0; className = className.replaceAll("\\.", "\\\\") + ".class"; //The two slashes represent for meaning changing File file = new File(defaultTargetDir + className); FileInputStream in = null; in = new FileInputStream(file); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); while ((ch = in.read()) != -1) { buffer.write(ch); } in.close(); return buffer.toByteArray(); } public String getDefaultTargetDir() { return defaultTargetDir; } public void setDefaultTargetDir(String defaultTargetDir) { this.defaultTargetDir = defaultTargetDir; } } package com.cxz.classloader; import com.cxz.jiangyou.Say; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; /** * This classloader is like a template * which includes pre-loadClass and after-loadClass * @author Bernard * */ public class ComplexClassLoader extends ClassLoader { public ComplexClassLoader() { } public ComplexClassLoader(String defaultTargetDir) { this.defaultTargetDir = defaultTargetDir; } private String defaultTargetDir = "D:\\hotdeploys\\"; public Class<?> findClass(String className) throws ClassNotFoundException { byte[] classBytes = null; try { classBytes = loadByteCode(className); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return super.defineClass(className, classBytes, 0, classBytes.length); } private byte[] loadByteCode(String className) throws IOException { int ch = 0; className = className.replaceAll("\\.", "\\\\") + ".class"; //The two slashes represent for meaning changing File file = new File(defaultTargetDir + className); FileInputStream in = null; in = new FileInputStream(file); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); while ((ch = in.read()) != -1) { buffer.write(ch); } in.close(); return buffer.toByteArray(); } public String getDefaultTargetDir() { return defaultTargetDir; } public void setDefaultTargetDir(String defaultTargetDir) { this.defaultTargetDir = defaultTargetDir; } }
该类会自动加载d:\hotdeploys下的类文件.
下面这个就是测试类
Java代码
package com.cxz.classloader; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import com.cxz.jiangyou.Say; public class MultiThreadTest implements Runnable { private static final int portNum = 9090; private static final int sleepCycle = 3000; private Say sayer = null; private ComplexClassLoader loader = new ComplexClassLoader(); private String delpoyee = "com.cxz.jiangyou.Sample"; public MultiThreadTest() { hotDeploy(delpoyee); } public void startService() { while (true) { synchronized (sayer) { sayer.say(); } try { Thread.sleep(sleepCycle); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void hotDeploy(String name) { try { if (sayer != null) { synchronized (sayer) { loader = new ComplexClassLoader(); sayer = (Say) loader.loadClass(name).newInstance(); } System.out.println("-------------->Hot deployment finished!"); } else { sayer = (Say) loader.loadClass(name).newInstance(); System.out.println("-------------->Initialization finished!"); } } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void run() { ServerSocket server = null; Socket socket = null; try { server = new ServerSocket(portNum); while (true) { socket = server.accept(); socket.close(); hotDeploy(delpoyee); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { // new MultiThreadTest().startService(); // new MultiThreadTest().run(); MultiThreadTest test = new MultiThreadTest(); Thread thread = new Thread(test); thread.start(); try { thread.sleep(sleepCycle); //Waiting for the deployment Thread deploy the say obj. } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } test.startService(); } } package com.cxz.classloader; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import com.cxz.jiangyou.Say; public class MultiThreadTest implements Runnable { private static final int portNum = 9090; private static final int sleepCycle = 3000; private Say sayer = null; private ComplexClassLoader loader = new ComplexClassLoader(); private String delpoyee = "com.cxz.jiangyou.Sample"; public MultiThreadTest() { hotDeploy(delpoyee); } public void startService() { while (true) { synchronized (sayer) { sayer.say(); } try { Thread.sleep(sleepCycle); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void hotDeploy(String name) { try { if (sayer != null) { synchronized (sayer) { loader = new ComplexClassLoader(); sayer = (Say) loader.loadClass(name).newInstance(); } System.out.println("-------------->Hot deployment finished!"); } else { sayer = (Say) loader.loadClass(name).newInstance(); System.out.println("-------------->Initialization finished!"); } } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void run() { ServerSocket server = null; Socket socket = null; try { server = new ServerSocket(portNum); while (true) { socket = server.accept(); socket.close(); hotDeploy(delpoyee); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void main(String[] args) { // new MultiThreadTest().startService(); // new MultiThreadTest().run(); MultiThreadTest test = new MultiThreadTest(); Thread thread = new Thread(test); thread.start(); try { thread.sleep(sleepCycle); //Waiting for the deployment Thread deploy the say obj. } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } test.startService(); } }
main线程主要是服务线程,通过调用startService()不停的通过system.out来打印。支线程负责监听端口(9090),当有连接信号后就重新加载类。
服务接口很简单,如下
Java代码 package com.cxz.jiangyou; public interface Say{ public void say(); } package com.cxz.jiangyou; public interface Say{ public void say(); }
总结:所有的customerClassLoader都要加载与之相关的类(比如:父类、包含的类)。如果你需要override loadclass(string, boolean)绕过findLoadedClass()检测,只能引发java.lang.LinkageError:duplicate class definition for name: "com/cxz/jiangyou/Sample"因此,比较通用的重新加载方式应该就是new一个用户定义的classloader
- Research.rar (9.4 KB)
- 下载次数: 90
- sample.rar (1.8 KB)
- 下载次数: 87
评论
1 楼
changqingonly
2009-08-10
貌似你理解错了ClassLoader的用法了,不能每次都new一个新的ClassLoader来加载你的class文件,这样必然导致你的命名空间发生变更哈。
发表评论
-
Java 生成可执行exe
2011-01-06 09:18 2648第一步:完成Java GUI程序 在Eclipse下, ... -
java bean copy 反射实现代码
2008-10-20 17:09 2258import java.lang.reflect.*; ... -
ISO 8859 语言字符集详解
2008-10-07 14:14 2931ISO/IEC 8859-1,又称Latin-1 ... -
Unsupported major.minor version
2008-07-22 13:40 2526当你在编译Java时,遇到Unsupported major. ... -
两种方法删除ArrayList里重复元素
2008-07-10 16:00 172141.方法一: /** List order not mai ... -
java compileClassLoader
2008-07-01 21:15 994import java.io.*; /* A Co ... -
java runtime.exec() 的讲解(转贴)
2008-07-01 20:59 14039那就首先说点Runtime类吧,他是一个与JVM运行时环境有关 ... -
JDK5.0以上版本的特殊用途(转贴)
2008-07-01 16:29 1421jinfo:可以输出并修改运 ... -
提高java程序性能 (转贴)
2008-07-01 16:00 1464下面将提供一些在JAVA程序的设计和编码中,为了能够提高JAV ... -
Java 中生成数字证书(转贴)
2008-07-01 15:52 28821、创建证书 Java 中的 ... -
java虚拟机参数2 (转贴)
2008-06-29 17:22 1599JVM配置参数中文说明: ------------------ ... -
java虚拟机参数1 (转贴)
2008-06-27 17:14 1254下面的讨论以Windows平台的Sun MicroSystem ... -
java 生成excel
2008-06-24 17:16 8689java 生成excel 示例代码 //** *** ... -
java 陷阱 3 最后的笑声
2008-06-20 21:28 1215下面的程序打印的内容? Java代码 public cla ... -
java 陷阱2 动物状元
2008-06-20 21:27 927Java代码 下面的java ... -
java 陷阱 1 增量
2008-06-20 21:25 1216下面的程序对一个变量重复的进行增量操作,然后打印它的值,那么打 ... -
classloader 总结
2008-06-20 20:59 1597classloader对我来说一直都是很神秘的东东,这两天一直 ... -
CompilingClassLoader
2008-06-20 20:54 1109import java.io.*; /* ... -
java 动态加载
2008-06-20 20:51 1909package com.cxz.thinking.act10; ... -
两段java代码的比较
2008-06-06 12:45 1169import java.util.ArrayList; ...
相关推荐
eclipse工程格式 博文链接:https://aga.iteye.com/blog/200818
热部署插件的实现原理主要是通过Agent字节码增强、Javassist、Classloader等技术来实现的。Agent字节码增强是指在Java字节码中插入一些用于热部署的代码,以便在运行时可以实现热部署。Javassist是一个Java库,提供...
Java热部署主要涉及到JVM(Java虚拟机)和类加载器(ClassLoader)的工作机制。JVM在运行时会加载类文件到内存中,当类被修改后,热部署插件能够检测到这种变化,并替换内存中的旧版本类,而不需要停止服务。这个...
这篇博文“JAVA类加载器分析--热部署的缺陷”探讨了Java类加载机制以及在热部署场景下可能遇到的问题。热部署允许开发者在不重启应用的情况下更新代码,提高开发效率,但同时也存在一些挑战。 首先,我们来理解类...
要实现热部署,关键在于自定义类加载器(ClassLoader)。通常,JVM 使用双亲委派模型加载类,即从顶层的 Bootstrap ClassLoader 开始,逐级向下查找直至找到合适的类加载器。自定义 ClassLoader 需要监控特定类的...
本文将详细介绍如何在Spring Tool Suite (STS) 中为Spring Boot项目设置热部署,以及DevTools的工作原理。 首先,要在Spring Boot项目中启用热部署功能,需要在`pom.xml`文件中添加`spring-boot-devtools`依赖。这...
总之,Java热部署是通过自定义ClassLoader、监控文件变化以及在必要时重新加载类来实现的。虽然JVM规范不直接支持这一功能,但通过各种策略和工具,开发者可以享受到类似Rails那样的便捷开发体验。
Java类热替换技术通常涉及类加载器(ClassLoader)的自定义以及字节码处理。本资料将通过源码分析,讲解如何实现这一功能。 首先,我们需要理解Java的类加载机制。在Java中,类加载器负责查找并加载类的字节码文件...