在Java中,打破单例模式的不同方式有哪些
在Java中,有哪些不同的方法可以打破单例模式。 我知道一种方法,即如果我们不在singleton中同步该方法,那么我们可以创建多个类的实例。因此,应用了同步。有没有办法打破单例java类在Java中,打破单例模式的不同方式有哪些,java,singleton,Java,Singleton,在Java中,有哪些不同的方法可以打破单例模式。 我知道一种方法,即如果我们不在singleton中同步该方法,那么我们可以创建多个类的实例。因此,应用了同步。有没有办法打破单例java类 public class Singleton { private static Singleton singleInstance; private Singleton() { } public static Singleton getSingleInstance() {
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;
}
}
多线程是单线程的最大问题。 您可以通过同步或使用即时初始化来避免这种情况 另一种方法是在你不应该使用的地方使用singleton。通过使用单例模式,您可能会以某种方式应用它,从而妨碍您的程序在以后的开发。(例如,在游戏中创建一个单人“玩家”,因为您假设它是一个单人游戏。开发的下一步是“添加合作功能”)
单例模式有它的优点,但不要在没有仔细考虑的情况下使用它。好吧,有两种方法可以打破它
- 使用反射
- 当有自定义类加载器时,不止一个(即父类加载器)。所有单例都应由公共父类加载器加载
getSingleInstance(){}
同步化
:
public synchronized static Singleton getSingleInstance() {
if (singleInstance == null) {
singleInstance = new Singleton();
}
return singleInstance;
}
除此之外,我认为破解密码并不容易。当然,如果添加递归调用,则可能会中断它,如下所示:
- 调用此
构造函数中其他类的构造函数单例
- 在该类的构造函数中,尝试获取这个
实例Singleton
但这是我能想到的唯一一件事,在
单例
类中,你无法保护自己不受此影响。从给定的代码开始,“双重检查锁定”可以在某些环境中被破解,
在使用Symantec JIT的系统上运行时,它不起作用。特别是,Symantec JIT编译
singletons[i].reference = new Singleton();
请注意,Symantec JIT使用基于句柄的对象分配系统
如您所见,对Singleton[i]的赋值是在调用Singleton的构造函数之前执行的。在现有java内存模型下,这是完全合法的,在C和C++中也是合法的(因为它们都没有内存模型)。
除此之外
可序列化
反射
(我相信)*如何解决违反规则的问题?
readResolve()
方法并引发异常clone()
并抛出CloneNotSupported
异常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();
}
}
毕竟,我建议使用Enum作为Singleton最安全的方法(因为java5最好的方法是使用Enum)
一种方法是序列化。如果未实现readResolve,则使用ObjectInputStream.readObject()读取单例将返回此单例的新实例。实际上,不需要同步的安全版本是: 其他安全版本包括:
正如其他人所写,您可以通过反序列化来打破其中的一些模式。阅读Joshua Bloch的《有效Java》(第74至78项)中有关防止此类攻击的内容(enum singleton模式是安全的,可以随时抵御此类攻击)。同步方法将起作用,但也会减慢对singleton的每次访问,以保护仅在第一次访问中发生的某些事情 最简单和最安全的方法就是进行快速初始化,这总是安全的,因为Java保证在允许任何人访问之前设置所有成员变量
public class Singleton {
private static Singleton singleInstance = new Singleton();
private Singleton() {
}
public static Singleton getSingleInstance() {
return singleInstance;
}
}
即使使用同步循环,您当前的方法实际上也是失败的——因为双重检查锁定被破坏了。如果要将singleton变量用于双重检查锁定,则需要将其标记为volatile,否则线程仍然可以访问未完全初始化的对象。有关更多详细信息,请参阅。假设您已将Singleton类实现为“SingletonPattern”,如下所示。 包com.example.pattern
public class SingletonPattern
{
private static SingletonPattern pattern;
public static SingletonPattern getInstance()
{
if (pattern == null)
{
synchronized (SingletonPattern.class)
{
if (pattern == null)
{
pattern = new SingletonPattern();
}
}
}
return pattern;
}
}
现在,您可以使用以下方法打破这个类的单例行为
Class c = Class.forName("com.example.pattern.SingletonPattern");
System.out.println((SingltonPattern) c.newInstance());
**单重试验**
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/***
*
* Ways to break Singleton
*/
public class Main {
private static ObjectInputStream inputStream;
public static void main(String[] args) throws Exception {
Singleton orginalSingletonObject = Singleton.getInstance();
/***
* Singleton is broken by using Reflection
*/
breakSingletonByReflection(orginalSingletonObject);
/***
* By Serialization/De-Serialization break Singleton We need
* Serialization interface in a class nedds to be serialized like
* Singleton.java
*/
breakSingletonByserialization(orginalSingletonObject);
/***
* By Cloning break Singleton
* We need to implement Cloneable interface
*/
breakSingletonByCloning(orginalSingletonObject);
/***
* Break Singleton By thread
* This scenario is related to multi-threading environment
*
*/
breakSingletonByThreading(orginalSingletonObject);
}
private static void breakSingletonByThreading(Singleton orginalSingletonObject) {
ExecutorService executorService=Executors.newFixedThreadPool(2);
/**
* Run this code snippet after commenting the other code for better understanding
* Run it repeatly to create a condition when 2 threads enter the method getInstance() of Singleton class at a same time
* When 2 threads enter the getInstance method at same time they will get the singleton object as null (private static Singleton singleton in Singleton.java)
* Then they will create two different objects ( have different hashcode) in this case singleton pattern will break.
*/
executorService.submit(Main::useSingleton); // JAVA 8 syntax it will get the singleton instance
executorService.submit(Main::useSingleton);
executorService.shutdown();
}
public static void useSingleton(){
Singleton singleton=Singleton.getInstance();
printSingletonData("By Threading", singleton);
}
private static void breakSingletonByCloning(Singleton orginalSingletonObject) throws CloneNotSupportedException {
Singleton clonedSingletonObject=(Singleton) orginalSingletonObject.clone();
printSingletonData("By Cloning", orginalSingletonObject, clonedSingletonObject);
}
private static void breakSingletonByReflection(Singleton orginalsingleton)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
Class<?> singletonClass = Class.forName("SingletonTest.Singleton");
@SuppressWarnings("unchecked")
Constructor<Singleton> constructor = (Constructor<Singleton>) singletonClass
.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton s = constructor.newInstance();
printSingletonData("By Reflection", orginalsingleton, s);
}
private static void breakSingletonByserialization(Singleton orginalsingleton)
throws FileNotFoundException, IOException, ClassNotFoundException {
/**
* Serialization
*/
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("E:\\Singleton.ser"));
outputStream.writeObject(orginalsingleton);
outputStream.close();
/**
* DeSerialization
*/
inputStream = new ObjectInputStream(new FileInputStream("E:\\Singleton.ser"));
Singleton deserializeObject = (Singleton) inputStream.readObject();
deserializeObject.hashCode();
printSingletonData("By Serialization", orginalsingleton, deserializeObject);
}
public static void printSingletonData(String operationName,
Singleton orginalsingleton, Singleton reflectionSigletonObject) {
System.out.println("------------------------------------------");
System.out.println("New Operation");
System.out.println(operationName);
System.out.println("orginal Hashcode=" + orginalsingleton.hashCode());
System.out.println("New Object hashcode="
+ reflectionSigletonObject.hashCode());
Boolean value = orginalsingleton.hashCode() != reflectionSigletonObject.hashCode();
System.out.println("These Object have different hascode. They are two different object Right = "
+ value);
System.out.println("As these are different Object this means Singleton Pattern is broken");
}
private static void printSingletonData(String operationName,Singleton singleton) {
System.out.println("------------------------------------------");
System.out.println("New Operation");
System.out.println(operationName);
System.out.println("Object hashcode=" + singleton.hashCode());
}
}
import java.io.FileInputStream;
导入java.io.FileNotFoundException;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.io.ObjectInputStream;
导入java.io.ObjectOutputStream;
导入java.lang.reflect.Constructor;
导入java.lang.reflect.InvocationTargetException;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
/***
*
*打破单身的方法
*/
公共班机{
私有静态对象inputStream inputStream;
公共静态void main(字符串[]args)引发异常{
Singleton orginalSingletonObject=Singleton.getInstance();
/***
*Singleton是通过使用反射来打破的
*/
breakSingletonByReflection(原始SingleTonObject);
/***
*通过序列化/反序列化打破我们需要的单例
*类中要序列化的序列化接口,如
*Singleton.java
*/
breakSingletonByserialization(orginalSingletonObject);
/***
*通过克隆打破单身
*我们需要实现克隆
public enum Singleton{
INSTANCE;
}
public class Singleton {
private static Singleton singleInstance = new Singleton();
private Singleton() {
}
public static Singleton getSingleInstance() {
return singleInstance;
}
}
public class SingletonPattern
{
private static SingletonPattern pattern;
public static SingletonPattern getInstance()
{
if (pattern == null)
{
synchronized (SingletonPattern.class)
{
if (pattern == null)
{
pattern = new SingletonPattern();
}
}
}
return pattern;
}
}
Class c = Class.forName("com.example.pattern.SingletonPattern");
System.out.println((SingltonPattern) c.newInstance());
import java.io.Serializable;
public class Singleton implements Serializable,Cloneable{
private static final long serialVersionUID = 1L;
private static Singleton singleton=null;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/***
*
* Ways to break Singleton
*/
public class Main {
private static ObjectInputStream inputStream;
public static void main(String[] args) throws Exception {
Singleton orginalSingletonObject = Singleton.getInstance();
/***
* Singleton is broken by using Reflection
*/
breakSingletonByReflection(orginalSingletonObject);
/***
* By Serialization/De-Serialization break Singleton We need
* Serialization interface in a class nedds to be serialized like
* Singleton.java
*/
breakSingletonByserialization(orginalSingletonObject);
/***
* By Cloning break Singleton
* We need to implement Cloneable interface
*/
breakSingletonByCloning(orginalSingletonObject);
/***
* Break Singleton By thread
* This scenario is related to multi-threading environment
*
*/
breakSingletonByThreading(orginalSingletonObject);
}
private static void breakSingletonByThreading(Singleton orginalSingletonObject) {
ExecutorService executorService=Executors.newFixedThreadPool(2);
/**
* Run this code snippet after commenting the other code for better understanding
* Run it repeatly to create a condition when 2 threads enter the method getInstance() of Singleton class at a same time
* When 2 threads enter the getInstance method at same time they will get the singleton object as null (private static Singleton singleton in Singleton.java)
* Then they will create two different objects ( have different hashcode) in this case singleton pattern will break.
*/
executorService.submit(Main::useSingleton); // JAVA 8 syntax it will get the singleton instance
executorService.submit(Main::useSingleton);
executorService.shutdown();
}
public static void useSingleton(){
Singleton singleton=Singleton.getInstance();
printSingletonData("By Threading", singleton);
}
private static void breakSingletonByCloning(Singleton orginalSingletonObject) throws CloneNotSupportedException {
Singleton clonedSingletonObject=(Singleton) orginalSingletonObject.clone();
printSingletonData("By Cloning", orginalSingletonObject, clonedSingletonObject);
}
private static void breakSingletonByReflection(Singleton orginalsingleton)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
Class<?> singletonClass = Class.forName("SingletonTest.Singleton");
@SuppressWarnings("unchecked")
Constructor<Singleton> constructor = (Constructor<Singleton>) singletonClass
.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton s = constructor.newInstance();
printSingletonData("By Reflection", orginalsingleton, s);
}
private static void breakSingletonByserialization(Singleton orginalsingleton)
throws FileNotFoundException, IOException, ClassNotFoundException {
/**
* Serialization
*/
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("E:\\Singleton.ser"));
outputStream.writeObject(orginalsingleton);
outputStream.close();
/**
* DeSerialization
*/
inputStream = new ObjectInputStream(new FileInputStream("E:\\Singleton.ser"));
Singleton deserializeObject = (Singleton) inputStream.readObject();
deserializeObject.hashCode();
printSingletonData("By Serialization", orginalsingleton, deserializeObject);
}
public static void printSingletonData(String operationName,
Singleton orginalsingleton, Singleton reflectionSigletonObject) {
System.out.println("------------------------------------------");
System.out.println("New Operation");
System.out.println(operationName);
System.out.println("orginal Hashcode=" + orginalsingleton.hashCode());
System.out.println("New Object hashcode="
+ reflectionSigletonObject.hashCode());
Boolean value = orginalsingleton.hashCode() != reflectionSigletonObject.hashCode();
System.out.println("These Object have different hascode. They are two different object Right = "
+ value);
System.out.println("As these are different Object this means Singleton Pattern is broken");
}
private static void printSingletonData(String operationName,Singleton singleton) {
System.out.println("------------------------------------------");
System.out.println("New Operation");
System.out.println(operationName);
System.out.println("Object hashcode=" + singleton.hashCode());
}
}
Constructor constructor = cls.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton singleton = (Singleton) constructor.newInstance();