`
robertliudeqiang
  • 浏览: 123143 次
  • 性别: 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错误

相关推荐

    用enum实现单例模式的方法来读取配置文件

    首先,我们来看一下传统的单例模式实现方式,如懒汉式和饿汉式,但这些方法在多线程环境下可能会存在问题。而使用枚举实现单例模式则能确保线程安全,且避免了序列化问题,是Java推荐的一种实现方式。 ```java ...

    单例模式垃圾回收_动力节点Java学院整理

    单例模式是一种常见的软件设计模式,它保证一个类只有一个实例,并提供全局访问点。在Java中,单例模式通常通过静态方法实现,如`getInstance()`,这样可以确保在整个应用程序生命周期中,类只会创建一个对象。然而...

    设计模式面试专题.zip

    - 在JVM中,单例模式被广泛应用于加载类的ClassLoader。 - Spring框架大量使用了工厂模式、单例模式、代理模式和装饰器模式。 - Java集合框架中,如ArrayList和LinkedList实现了迭代器模式,HashMap实现了策略...

    深入Java虚拟机_ClassLoader

    "双重检查锁定"是一种设计模式,用于确保类的单例属性,同时避免不必要的同步开销。在类加载过程中,这个模式能确保类只被加载一次。 5. 类的全限定名与类加载: 类的全限定名是类的完全标识,包括包名和类名,...

    java面试题

    - 单例模式不能扩展为多例模式,且不应由其他类创建实例。 - 单例模式在只有一个实例需要时使用,全程变量可以通过单例模式实现。 6. **设计模式**: - Java I/O库中的装饰者模式用于动态组合功能。 - Session...

    JavaAP和PG试题.pdf

    A选项错误,单例模式设计初衷即为单例,不易扩展为多例。B选项错误,单例实例由模式自身管理。D选项错误,全局变量本身即为全局可见,无需单例模式。 6. **设计模式**:A选项正确,Java I/O库中的装饰器模式常用于...

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

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

    Java高并发编程详解:多线程与架构设计 (Java核心技术系列)

    作者阐述了`volatile`关键字的语义,如何保证并发环境下的数据一致性,并通过实例演示了如何在单例设计模式中应用`volatile`,以实现线程安全的单例。 第四部分是多线程设计架构模式,涵盖了多种用于提高并发性能...

    Singleton 设计模式

    4. **简化并发控制**:在多线程环境下,Singleton 可以简化对实例化过程的同步控制,确保在并发环境中正确地创建单例。 然而,Singleton 模式也存在一些问题和争议: 1. **反模式**:在某些设计原则(如面向对象的...

    Java程序员反馈的百度的笔试题.docx

    单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。常见的实现方式有饿汉式(静态常量)、懒汉式(线程不安全的、线程安全的synchronized和双重检查锁定)以及枚举单例。 4. **重写equals...

    java工程师面试题 经典并且有用

    - **单例模式**:介绍单例模式的实现方式,如饿汉式、懒汉式、双重检查锁定等。 - **工厂模式**:讲解简单工厂、工厂方法和抽象工厂模式的区别和应用场景。 7. **IO流** - **字符流与字节流**:区分两者的处理...

    java 继承关系的加载顺序

    在单例模式中,通常使用私有构造器防止多次实例化。如果子类继承了单例类,必须注意不要破坏单例的性质。通常通过抽象工厂或枚举来解决这个问题。 总结,Java中继承关系的加载顺序遵循“先父后子”的原则,从加载...

    最全java八股文高级/资深面试题

    2. **单例模式**:为了安全地创建单例,推荐使用双重检查锁定(Double-Check Locking)或枚举单例模式。双重检查锁定利用`volatile`关键字确保线程安全,避免多线程环境中的多次实例化;枚举单例是Java中最安全且...

    Java面试题目和答案.pdf

    15. **单例模式与多例的区别**: - **单例模式**确保一个类只有一个实例,并提供一个全局访问点。 - **多例模式**允许类有多个实例,并通过工厂模式控制实例的创建。 16. **工厂模式及其分类**: - **工厂模式**...

    JAVA公共资源模块的设计与开发(源代码+论文)

    对于那些全局唯一且需要频繁使用的公共资源,如数据库连接池,通常采用单例模式。这样可以确保系统中只有一个实例,节省资源并防止并发问题。 6. **依赖注入**: 使用Spring等框架实现依赖注入,可以将公共资源的...

    115个Java经典面试题和答案

    - 单例模式、工厂模式、装饰器模式、代理模式等23种设计模式的解释和应用实例。 10. **Spring框架** - Spring的核心模块:Core、DI、AOP、MVC。 - 注解驱动开发:@Autowired、@Component、@Service、@Repository...

    海辉笔试题

    1. **单例模式**:单例模式确保某个类只有一个实例,并提供一个全局访问点。 - **特点**:确保在程序运行期间只存在一个实例。 - **应用场景**:适用于配置管理、日志记录、线程池等场景。 2. **Java I/O库**:...

    java面试小技巧

    单例模式、工厂模式、代理模式和适配模式是Java中常用的几种设计模式,它们各有不同的应用场景和优势。理解这些设计模式的原理和实现,能够帮助开发者写出更加模块化和可维护的代码。 最后,理解面向对象编程的设计...

    java面试宝典

    - 单例模式:了解懒汉式、饿汉式、双重检查锁定等多种实现方式。 - 观察者模式:理解事件驱动和发布订阅模型。 - 代理模式:静态代理和动态代理(JDK动态代理与CGLIB)的实现。 - 适配器模式、装饰者模式、策略...

Global site tag (gtag.js) - Google Analytics