1. Gossip less, directly on the code.
Import java.io.Serializable;
A Hungry man type
public class Singleton01 implements serializable{
1. Private properties
private static Singleton01 instance=new Singleton01 ();
2. Private constructors
Private Singleton01 () {}
3. A common get () method
public static Singleton01 getinstance () {//There is no need to add a synchronization block here synchronized
return instance;
}
}
Why don't I need to add a sync block? Here's a short message.
1. The A hungry man is naturally thread-safe and therefore does not require an add-on lock. A hungry man is a natural thread-safe because:
A bytecode file that is loaded into memory undergoes the following process:
1, Link (1, Verification 2, preparation 3, analysis)
2. Initialization
3. Use
4. Uninstall
Initialization is the process of executing the class constructor <clinit> () method. The class constructor <clinit> () method is generated by the compiler's automatic collection of assignment actions for all class variables in the class and statements in static statement blocks (static). In this process, the instance has been instantiated. and the virtual machine JVM guarantees that the <clinit> () method of a class is properly locked and synchronized in a multithreaded environment. So he is naturally thread-safe.
2. The following code analyzes how to use reflection to crack lazy-type:
public class Singletons_test_02 {
public static void Main (string[] args) throws Exception {
Class<singleton01> clazz = (class<singleton01>) class.forname ("Com.shc.singleton.Singleton01");
constructor<singleton01> c = clazz.getdeclaredconstructor (null);//Get parameterless constructor
C.setaccessible (TRUE);//skip permission checks to access private constructors
Singleton01 s3 = C.newinstance ();
Singleton01 S4 = C.newinstance ();
System.out.println (S3);
System.out.println (S4);
}
}
At this point the output S3 is equal to the hash value of S4. Representatives are not the same object, a hungry man-type singleton is done by reflection cracking.
3. The following analysis a hungry man how to avoid reflection vulnerability?
public class Singleton1 {
1. Private properties
private static Singleton1 instance=new Singleton1 ();
2. Private constructors
Private Singleton1 () {
if (null! = instance) {
throw new RuntimeException ();
}
}
3. A common get () method
public static Singleton1 getinstance () {//Natural thread-safe, no need to add synchronization blocks, so the call efficiency is high
return instance;
}
}
Add a judgment in the private constructor to determine if the object to be created exists, and if it does not exist again, throws a run-time exception if it is already present.
4. Use the following serialization and deserialization vulnerability to crack the A hungry man type of single case
public class Singletons_test_03 {
public static void Main (string[] args) throws Exception {
Singleton01 S1 = singleton01.getinstance ();
Singleton01 s2 = singleton01.getinstance ();
System.out.println (S1);
SYSTEM.OUT.PRINTLN (S2);
Serialization of
FileOutputStream fos = new FileOutputStream (".. /a.txt ");
ObjectOutputStream oos = new ObjectOutputStream (FOS);
Oos.writeobject (S1);
Oos.close ();
Fos.close ();
Deserialization
ObjectInputStream ois =new ObjectInputStream (New FileInputStream (". /a.txt "));
Singleton01 s3 = (Singleton01) ois.readobject ();
System.out.println (S3);
}
}
5. Cracking a hungry man-type deserialization vulnerability
public class Singleton11 implements serializable{
1. Private properties
private static Singleton11 instance=new Singleton11 ();
2. Private constructors
Private Singleton11 () {}
3. A common get () method
public static Singleton11 getinstance () {
return instance;
}
When deserializing (add this method to prevent deserialization of the vulnerability)
Private Object Readresolve () throws objectstreamexception{
return instance;
}
}
The above demo is relatively simple, do not do in-depth research, design mode experience heavy application.
(One-case design mode) A hungry man reflection and deserialization vulnerability