当前位置: 首页 > 面试题库 >

用其他方法破解单例

元鸿波
2023-03-14
问题内容

我正在研究单例,并且已经开发了非常基本的单例类。

public class SingletonObject {
    private static SingletonObject ref;
    private SingletonObject () //private constructor
    { }

    public  static synchronized   SingletonObject getSingletonObject()
    {
        if (ref == null)
            ref = new SingletonObject();
                return ref;
        }


    public Object clone() throws CloneNotSupportedException
    {throw new CloneNotSupportedException ();
    }   
}

现在下面是我破解单例的一种方法。

public class CrackingSingleton {

     public static void main(String[] args) throws ClassNotFoundException,
       IllegalArgumentException, SecurityException,
       InstantiationException, IllegalAccessException,
       InvocationTargetException {

        //First statement retrieves the Constructor object for private constructor of SimpleSingleton class.
        Constructor pvtConstructor = Class.forName("CrackingSingleton.SingletonObject").getDeclaredConstructors()[0];
        //Since the constructor retrieved is a private one, we need to set its accessibility to true.
        pvtConstructor.setAccessible(true);
        //Last statement invokes the private constructor and create a new instance of SimpleSingleton class.
         SingletonObject  notSingleton1 = ( SingletonObject) pvtConstructor.newInstance(null);
         System.out.println(notSingleton1.hashCode());
         System.out.println("notSingleton1 --->"+notSingleton1.toString());
         SingletonObject  notSingleton2 = ( SingletonObject) pvtConstructor.newInstance(null);
         System.out.println("notSingleton2 --->"+notSingleton2.hashCode());
         System.out.println(notSingleton2.toString());
    }
}

请也建议其他方法可以使单例破裂.. !!


问题答案:

我可以想到的三种方法是:

序列化

如果您的单例类是可序列化的,则可以序列化它的一个实例,然后反序列化它,以获得该类的第二个对象。

您可以通过实现readResolve方法来避免这种情况。

public class Singleton implements Serializable {
   private static final Singleton INSTANCE = new Singleton();

   public static Singleton getInstance(){
       return INSTANCE;
   }

   public Object readResolve() throws ObjectStreamException {
        return INSTANCE; //ensure singleton is returned upon deserialization.
   }
}

类加载

可以由两个不同的类加载器加载同一个类,这样,您可以通过getInstance在两个不同的类加载器加载的类中简单地调用其方法来创建单例类的两个实例。这种方法将有效,
而不必诉诸于私有构造函数

ClassLoader cl1 = new URLClassLoader(new URL[]{"singleton.jar"}, null);
ClassLoader cl2 = new URLClassLoader(new URL[]{"singleton.jar"}, null);
Class<?> singClass1 = cl1.loadClass("hacking.Singleton");
Class<?> singClass2 = cl2.loadClass("hacking.Singleton");
//...
Method getInstance1 = singClass1.getDeclaredMethod("getInstance", ...);
Method getInstance2 = singClass2.getDeclaredMethod("getInstance", ...);
//...
Object singleton1 = getInstance1.invoke(null);
Object singleton2 = getInstance2.invoke(null);

反射

如您所指出的,通过反射,您可以创建该类的两个实例。我认为前面的示例只是该方法的一种变体。但是我相信您可以使用来防止这两种情况的发生SecurityManager

System.setSecurityManager(new SecurityManager());


 类似资料:
  • 其他认证方法 还有两种其他身份验证方法值得一提。它们是一次性密码和证书。 一次性密码 FreeRADIUS包含一个名为rlm_otp的模块,可用于处理OTP(一次性密码)令牌。该模块应与其他程序一起使用。 不幸的是,为其他程序提供代码的公司Tri-D Systems已经不存在了。但是,代码是分叉的,现在可以从Google Code(http://code.google.com/p/otpd/)获得

  • 问题内容: 如果我有两个类,而其中一个有一个要在其他类中使用的函数,那么该使用什么,这样就不必重写我的函数了? 问题答案: 有两种选择: 在您的类中实例化一个对象,然后在其上调用所需的方法 使用@classmethod将函数转换为类方法 例: 或使用继承(如果适用):

  • 本文向大家介绍WPF利用RPC调用其他进程的方法详解,包括了WPF利用RPC调用其他进程的方法详解的使用技巧和注意事项,需要的朋友参考一下 前言 如果在 WPF 需要用多进程通信,一个推荐的方法是 WCF ,因为 WCF 是 RPC 计算。先来讲下 RPC (Remote Procedure Call) 远程过程调用,他是通过特定协议,包括 tcp 、http 等对其他进程进行调用的技术。详细请看

  • 问题内容: 我正在尝试捕获WebBrowser控件的内容。可以完美地工作,但是WebBrowser控件的文档中不支持它。我一直在尝试寻找另一种捕获WebBrowser控件的内容并将其保存到本地图像文件的方法。 是否有人有任何变通办法或其他方法将WebBrowser控件的内容保存到本地图像文件? 问题答案: Control.DrawToBitmap并不总是能正常工作,因此我诉诸于以下提供更一致结果的

  • 前言 数组的其他方法如下: 方法 描述 备注 indexOf(value) 从前往后索引,获取 value 在数组中的第一个下标 lastIndexOf(value) 从后往前索引,获取 value 在数组中的最后一个下标 find(function()) 找出第一个满足「指定条件返回true」的元素。 findIndex(function()) 找出第一个满足「指定条件返回true」的元素的in