gpt4 book ai didi

java - 我们可以通过哪些不同的方式打破 Java 中的单例模式

转载 作者:搜寻专家 更新时间:2023-10-30 21:22:12 25 4
gpt4 key购买 nike

我们可以通过哪些不同的方式打破 Java 中的单例模式。我知道一种方法,即如果我们不同步 singleton 中的方法,那么我们可以创建多个类的实例。因此应用了同步。有没有办法打破单例 java 类。

public class Singleton {
private static Singleton singleInstance;

private Singleton() {
}

public static Singleton getSingleInstance() {
if (singleInstance == null) {
synchronized (Singleton.class) {
if (singleInstance == null) {
singleInstance = new Singleton();
}
}
}
return singleInstance;
}
}

最佳答案

从您给定的代码开始,“双重检查锁定”在某些环境下可能会被破坏,在使用 Symantec JIT 的系统上运行时,它不起作用。特别是 Symantec JIT 编译

singletons[i].reference = new Singleton();

以下内容(请注意,Symantec JIT 使用基于句柄的对象分配系统)。

0206106A   mov         eax,0F97E78h
0206106F call 01F6B210 ; allocate space for
; Singleton, return result in eax
02061074 mov dword ptr [ebp],eax ; EBP is &singletons[i].reference
; store the unconstructed object here.
02061077 mov ecx,dword ptr [eax] ; dereference the handle to
; get the raw pointer
02061079 mov dword ptr [ecx],100h ; Next 4 lines are
0206107F mov dword ptr [ecx+4],200h ; Singleton's inlined constructor
02061086 mov dword ptr [ecx+8],400h
0206108D mov dword ptr [ecx+0Ch],0F84030h

如您所见,对 singletons[i].reference 的赋值是在调用 Singleton 的构造函数之前执行的。这在现有的 Java 内存模型下是完全合法的,在 C 和 C++ 中也是合法的(因为它们都没有内存模型)。

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

除此之外

  1. 如果类是Serializable,它可以中断
  2. 如果它是“可克隆的”,它可能会崩溃
  3. 你可以通过Reflection来打破(我相信)
  4. 它可以中断多个类加载器加载类

*如何解决违反规则的问题?

  1. 主动初始化要安全得多
  2. 防止反序列化创建新对象你可以覆盖类中的 readResolve() 方法并抛出异常
  3. 为了防止克隆,你可以覆盖 clone() 并抛出 CloneNotSupported 异常
  4. 为了逃避反射实例,我们可以在构造函数中添加检查并抛出异常。

示例

public class Singleton {

private static final Singleton INSTANCE = new Singleton();

private Singleton() {
// Check if we already have an instance
if (INSTANCE != null) {
throw new IllegalStateException("Singleton" +
" instance already created.");
}
}
public static final Singleton getInstance() {
return INSTANCE;
}
private Object readResolve() throws ObjectStreamException {
return INSTANCE;
}
private Object writeReplace() throws ObjectStreamException {
return INSTANCE;
}
public Object clone() throws CloneNotSupportedException {
// return INSTANCE
throw new CloneNotSupportedException();
}
}

毕竟我建议使用枚举作为单例最安全的方式(因为 java5 最好的方法是使用枚举)

public static enum SingletonFactory {
INSTANCE;
public static SingletonFactory getInstance() {
return INSTANCE;
}
}

关于java - 我们可以通过哪些不同的方式打破 Java 中的单例模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20421920/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com