`
robertliudeqiang
  • 浏览: 121935 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

多classloader对单例模式的影响

    博客分类:
  • java
阅读更多
早上看了一篇写单例模式的文章,总结的比较全,可惜仍然没有对单例模式在不同classloader甚至是多个jvm上的分析,在网上搜了一下,找到一个例子并改写如下:

定义一个空接口:
// Null interface, do nothing but you'll see the usage later
public interface IAntiSingleton {
}


定义一个通用的单例模式
public class AntiSingleton implements IAntiSingleton {
	private static final AntiSingleton instance = new AntiSingleton();

	public static AntiSingleton getInstance() {
		return instance;
	}
}


继承一个classloader并生成AntiSingleton对象
public class NewClassLoader extends ClassLoader {
	public IAntiSingleton createNewOne() throws Exception {
		InputStream is = getClass().getResourceAsStream("AntiSingleton.class");
		byte[] b = new byte[is.available()];
		is.read(b);
		Class clz = defineClass(null, b, 0, b.length);
		Object o = clz.newInstance();
		return (IAntiSingleton) o;
	}
}


测试方法:
public class TestAntiSingleton {
	public static void main(String[] args) throws Exception {
		AntiSingleton instance = AntiSingleton.getInstance();
		NewClassLoader loader = new NewClassLoader();
		IAntiSingleton newObj = loader.createNewOne();
		System.out.println(AntiSingleton.getInstance() == newObj);
	}
}
output:
=========
false


总结:

java中,一个类可以有多个定义,并且这些类名可以相同(但同一个类加载器产生类的类名不能相同)。如果不同类加载器两个类名相同,即使类的定义相同,甚至一个类的定义是由另一个类产生的,这两个类也是不同的类。

这也就是输出结果产生false的原因,因为此时两个类虽然名字相同,但是其实已经不是一个类。此时的单例模式,看起来是失效的。注意上面为什么要用接口,因为此时在程序中直接使用NewClassLoader用AntiSingleton对输出结果进行转型,在运行时就会抛出一个类型转换Exception。

可以想到的一种情况是,tomcat中,可以部署很多项目,各个项目中是可以出现相同的类名的,这就需要不同的classloader分别load生成这些类。

此外,GoF计划对“设计模式”进行修订,其中提到了要剔除“单例模式”,很期待修订版早点出来。
分享到:
评论
2 楼 robertliudeqiang 2010-04-16  
上帝的后花园 写道
多嘴一下:
你这个AntiSingleton类不是单例模式,
因为没有将默认构造函数私有化。
私有化的默认构造函数是不能用class.newInstance()来调用的,否则会报java.lang.IllegalAccessException错误


这位朋友说的很对,其实我想说的意思是,对于多个classloader来说,另外的classloader是可以获取某个类的定义并产生一个“同名”的对象的。

以这个例子来说,即使我把构造函数设置成私有化,在另外一个classloader里不能调用class.newInstance()方法产生对象,但是另外一个classloader同样可以使用反射调用getInstance()来产生一个和之前不同的对象。而这两个对象的“名字”是相同的,只是在不同的classloader里。
1 楼 上帝的后花园 2010-04-14  
多嘴一下:
你这个AntiSingleton类不是单例模式,
因为没有将默认构造函数私有化。
私有化的默认构造函数是不能用class.newInstance()来调用的,否则会报java.lang.IllegalAccessException错误

相关推荐

    单例模式详解

    Singleton模式可以相当的复杂,比头五种模式加起来还复杂,譬如涉及到DCL双锁检测(double checked locking)的讨论、涉及到多个类加载器(ClassLoader)协同时、涉及到跨JVM(集群、远程EJB等)时、涉及到单例对象...

    day020-继承加强和设计模式代码和笔记.rar

    通过单例模式获取到对象后。就是只有一个对象的类 方法全部都是非static修饰的,调用方式:对象名.方法名(...); 4. 工具类命名: XxxUtil、XxxUtils、XxxTool、XxxTools 3. jar 包 (掌握)...

    JSP开发实用技术整理

    这是本人在开发和学习中长期整理出来的,个人认为比较实用,一共11份word文档...17. 单例模式 22 18. 工厂模式 23 19. 读取配置文件(1) 25 20. 根据libName动态加载jar类库 33 =================================== ....

    Java 基础面试题

    24. 手写单例模式中的懒汉式和饿汉 25. transient 这个关键字是干啥的 26. 什么是一致性hash算法 27. 构造方法链 28. 谈谈你对线程调度的理解 29. JDK动态代理和CGLIB动态代理 30. 反射机制以及反射的方式 31...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【设计模式】写一个单例(延迟加载,高性能) 144 【容器】Apache Http Server和Tomcat 区别 145 【版本控制】GIT与SVN的区别 146 【高并发】Java高并发解决方案 148 HTML静态化 149 图片服务器分离 149 数据库集群和库...

    java核心面试

    线程 单例模式下的线程安全http://blog.sina.com.cn/s/blog_75247c770100yxpb.html map集合 集合数据结构及方法的使用 多线程 线程进程 线程状态 线程状态的改变 sql :临时表、游标、存贮过程、触发机制...

    java核心面试技术点

    线程 单例模式下的线程安全http://blog.sina.com.cn/s/blog_75247c770100yxpb.html map集合 集合数据结构及方法的使用 多线程 线程进程 线程状态 线程状态的改变 sql :临时表、游标、存贮过程、触发机制...

    超级有影响力霸气的Java面试题大全文档

    超级有影响力的Java面试题大全文档 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节。...

    java 面试题 总结

    与cgi的区别在于servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,而CGI对每个请求都产生新的进程,服务完成后就销毁,所以效率上低于servlet。...

    JAVA核心知识点整理(有效)

    1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................

Global site tag (gtag.js) - Google Analytics