Private constructor protection for a single case of reflection destruction

Source: Internet
Author: User

Java's reflection destroys the private constructor protection of a singleton, most typically spring's bean injection, which we can prevent by transforming the private constructor.
In Singleton, we only provide factory methods (get Singleton), and privatization constructors, to prevent extraneous creation outside.
Private constructors are already safe for general external calls.

public class Singleton {private Singleton () {} private static volatile Singleton instance = null; public static singletongetinstance () throws Exception {if (instance ==null) {//For brevity, thread safety instance =new Singleton (  );} returninstance; }  }

  

  

Class Singletonclass = Class.forName ("Com.jscai.spring.demo.Singleton"); constructor[] cts = Singletonclass.getconstructors (); System.out.println (Cts.length)


The general external call, the compiler will check, directly prompt the compilation error. The normal reflection also cannot find the private constructor, so the above output is 0.
However, some privileged users can access private constructors through reflection and instantiate:
  

Constructor[] cts = Singletonclass.getdeclaredconstructors (); System.out.println (cts.length); Cts[0]. Setaccessible (true); Singletonsingleton = (Singleton) cts[0].newinstance ();

  


The code above first obtains all constructors (Public,protected,default * (package) access, andprivate constructors) through the reflected getdeclaredconstructors () , of course, this function verifies the caller's permissions.
The private constructor cannot be called by default, and the access rights must be opened setaccessible (true) to access the private constructor, which destroys the private constructor protection of the singleton.
If you want to defend against such a reflection intrusion, you can modify the constructor, plus the second instantiation of the check. (The above getinstance () is processed by multithreading (Doublecheck), so there is no thread conflict to trigger this exception)

private static int cntinstance = 0;private Singleton () throws Exception {if (++cntinstance > 1) {throw new Exception ("C An ' tcreate another instance. " );}        }

  


In addition, in Spring bean injection, even if you privatize the constructor, by default he will call your private constructor to instantiate the function. "Assemble the beans through beanfactory, as in the logic above"
So, if we want to guarantee the uniqueness of the instance, we need to add the factory-method= "" attribute to the definition <bean>, and the defense mechanism in the private constructor. The getinstance () of the singleton may add some logic, and spring's default call to the constructor to create it does not guarantee the accuracy of this logic, so it poses a hidden danger.
We can test whether a singleton was created multiple times by scope= "prototype":

<beanid= "Test" class= "Com.jscai.spring.demo.Singleton" scope= "prototype" ></bean> beanfactory bf = new  Classpathxmlapplicationcontext ("Demoapptestcontext.xml"); Singleton test1 = (Singleton) bf.getbean ("Singleton"); Singleton test2 = (Singleton) bf.getbean ("Singleton");

  


Find the defense mechanism in effect, throw "Can ' t create another instance." Exception, which proves that spring can normally call the private constructor to create the bean and create it several times.
At this time we will use Factory-method to specify the factory method, in order to achieve the effect we want
  

<beanid= "Test" class= "Com.jscai.spring.demo.Singleton" scope= "prototype" factory-method= "getinstance" ></ Bean>

  

Private constructor protection for a single case of reflection destruction

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.