- 浏览: 218501 次
- 性别:
- 来自: 天津
文章分类
最新评论
-
flychao88:
nothingismao 写道623deyingxiong 写 ...
nio与io的比较 -
李冰冰:
如果NIO单个线程处理业务逻辑,那么如果这个业务逻辑非常耗时, ...
nio与io的比较 -
wj_126mail:
IO是一个连接就创建一个线程来处理;NIO是一个线程在处理所有 ...
nio与io的比较 -
nothingismao:
623deyingxiong 写道wwj85523 写道 看完 ...
nio与io的比较 -
623deyingxiong:
wwj85523 写道
看完后我迷糊了,
IO一样可以一个线 ...
nio与io的比较
这两天一直在学习一些classloader的相关知识,看了一些文章,了解到classloader的作用之一就是实现热部署功能。于是就看了一个网络上的一个例子,然后自己实现了一个应用。虽然作出来了,但是说实话:不满意。因为在这个例子当中,只要热部署一次,就要重新new一个classloader,这样会引发什么问题我也不清楚,并且,classloader究竟实现了什么,以及一些底层的东西我还不是很了解,还要继续研究,目前的版本就是一个中间版本。以后还要优化,或者在我读完tomcat的classloader之后我在去仿照着写一个。
好了,下面介绍这个工程的构思、以及实现方式,设计思想:首先来说:这个工程至少需要是需要2个线程,一个是类似tomcat的服务线程,另外一个就是检测线程,检测变化,重新加载Class对象。我猜tomcat是采取了检测类,检测加载了的类文件变化。我没有那么实现,因为这种实现方式相对复杂,并且我的想集中解决热部署问题,而不是如何实现监控文件,所以我就采取了相对简单的方式:socket通知方式。也就是,在我重新编译一个class之后,利用socket通知检测线程,监测监测在监测到socket命令之后会自动的加载。
该类会自动加载d:\hotdeploys下的类文件.
下面这个就是测试类
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
另一个例子
好了,下面介绍这个工程的构思、以及实现方式,设计思想:首先来说:这个工程至少需要是需要2个线程,一个是类似tomcat的服务线程,另外一个就是检测线程,检测变化,重新加载Class对象。我猜tomcat是采取了检测类,检测加载了的类文件变化。我没有那么实现,因为这种实现方式相对复杂,并且我的想集中解决热部署问题,而不是如何实现监控文件,所以我就采取了相对简单的方式:socket通知方式。也就是,在我重新编译一个class之后,利用socket通知检测线程,监测监测在监测到socket命令之后会自动的加载。
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下的类文件.
下面这个就是测试类
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),当有连接信号后就重新加载类。
服务接口很简单,如下
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
另一个例子
import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; public class TestSuite { private static final String dir = "D:\\depot\\dev\\"; public static Test suite() { TestSuite suite = new TestSuite(); Class clz = loadClass("com.cxz.test.bs.XXXXTest"); suite.addTestSuite(clz); return suite; } public static void bootstrap(String[] args) { junit.textui.TestRunner.run(suite()); } public static Class loadClass(String name) { File file = new File(dir); ClassLoader loader = null; Class clz = null; try { loader = new URLClassLoader(new URL[] { file.toURL() }); clz = loader.loadClass(name); } catch (MalformedURLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } // return clz; } /** * For test * * @param args */ public static void main(String[] args) { loadClass(""); } }
- sample.rar (1.8 KB)
- 下载次数: 31
- Research.rar (9.4 KB)
- 描述: eclipse工程格式
- 下载次数: 68
发表评论
-
ant build.xml例子
2010-01-10 20:16 2509<?xml version="1.0" ... -
避免内存泄露专题
2009-12-17 16:19 1233For Java: 1.限制使用单例模式;单例模式是引发mem ... -
万恶的inner class, memory leak的源头之一
2009-12-17 15:35 1325非static inner class隐式的含有一个引用指向o ... -
resolve maven [Request to merge when 'filtering' is not identical]. issue
2009-11-06 11:18 2707mvn org.apache.maven.plugins:ma ... -
an example of cloneable
2009-10-10 09:43 1079The following code describes ho ... -
jvm 远程debug
2009-04-17 10:01 1146-Xdebug -Xrunjdwp:transport=dt_ ... -
java dynamic proxy
2008-11-21 20:45 1132package proxy.cxz.org; impor ... -
serializable例子一则
2008-11-15 21:13 1054实现Serializable接口,编写地定义的针对transi ... -
jmx添加naming service以及一个rmi 监听方式
2008-11-11 15:22 2632ObjectName namingName = new ... -
指定编码器、解码器,并且利用ByteBuffer读写文件
2008-11-04 20:48 2687指定编码器、解码器,并且利用ByteBuffer读写文件。 做 ... -
java 网络编程探讨
2008-11-02 19:30 2096毕业有一年多了,大学的时候上过网络课程,但我一直认为:网络技术 ... -
Differences Between notify() and notifyAll()
2008-08-08 21:20 1051package com.cxz.currency.test; ... -
一套基于http的聊天c/s结构工具(除了网页tomcat还能做什么)
2008-08-08 11:51 4048在我的认识当中以前一直有一种误区认为:tomcat=web。在 ... -
jdk1.6中添加的future
2008-07-18 13:59 1327摘自:http://caterpillar.onlyfun.n ... -
模拟jdk1.5中reentrantlock
2008-07-18 13:15 1199选自:java线程2e。 类似于jdk1.5中的reentra ... -
java线程2e中写得相当花哨的thread例子!
2008-07-14 16:53 1782太鲜灵儿了! package com.cxz.tools; ... -
j2se中实现jndi的控制、管理
2008-07-01 19:34 1169jndi例子一则,转载自网络。利用一个container实现了 ... -
jmx控制tomcat
2008-07-01 09:22 5048以前所作的一切应用程序基本上都是由tomcat容器,控制web ... -
jmx例子一则
2008-06-30 07:32 2893很简单的一个hellojmx的例子。其中实现了:标准bean、 ... -
nio与io的比较
2008-06-21 17:31 14945nio是new io的简称,从jdk1.4就被引入了。现在的j ...
相关推荐
博文链接:https://kuangbaoxu.iteye.com/blog/206472
热部署插件的实现原理主要是通过Agent字节码增强、Javassist、Classloader等技术来实现的。Agent字节码增强是指在Java字节码中插入一些用于热部署的代码,以便在运行时可以实现热部署。Javassist是一个Java库,提供...
Java热部署技术是一种提高开发效率的重要工具,它允许开发者在运行时修改代码并立即生效,无需重新启动应用程序服务器。在传统的开发过程中,每次修改代码后都需要重新编译、打包,然后重启服务器才能看到更改的效果...
另一个问题是类的静态初始化器只会在类首次加载时执行,如果热部署过程中重新加载了类,静态初始化器不会再次执行,这可能会影响到依赖静态变量的逻辑。 解决这些问题的方法包括使用特殊的热部署插件,如JRebel,它...
ASM 是一个强大的 Java 字节码操控和分析框架,允许开发者动态生成类或修改已存在的类。ASM 首先读取 .class 文件,解析其中的元数据,然后允许开发者插入、删除或修改字节码指令,最后生成新的 .class 文件。通过 ...
上述代码展示了如何创建一个动态ClassLoader来实现热部署的基本思想。ManageClassLoader会检查类文件的修改时间,如果发现变化,就使用DynamicClassLoader加载新的字节码。 尽管Java标准版(J2SE)没有内置的热部署...
这是一个可选依赖,不会传递到依赖于你的项目的其他模块。在`pom.xml`中添加如下代码: ```xml <groupId>org.springframework.boot <artifactId>spring-boot-devtools <optional>true ``` 接着,在`...
1. **JRebel**:这是一个商业工具,它可以实时更新类、资源和配置文件,而无需重新部署应用。JRebel通过代理ClassLoader实现这一功能,但其核心原理并不开源。 2. **JVM工具JIT编译器**:Java虚拟机(JVM)的Just-...
自定义ClassLoader允许开发者根据特定需求加载类,比如动态加载或更新类文件,这在某些高级应用场景中非常有用,如插件系统、热部署等。本案例将深入探讨如何创建一个自定义的ClassLoader,利用Java反射和注解技术...
自定义ClassLoader是Java平台的一大特色,开发人员可以根据需要创建自己的类加载器,例如实现模块化、热部署或者加密解密类等高级功能。自定义ClassLoader通常需要重写findClass()或loadClass()方法,以控制类的加载...
自定义ClassLoader是一种常见的需求,例如在插件系统、热部署等场景。自定义加载器通常需要重写`loadClass(String className)`方法,通过URL读取类的字节流并转换为Class对象。在这个过程中,我们需要注意类的缓存,...