当前位置:网站首页>Implementation of singleton mode and prevention of reflection and serialization
Implementation of singleton mode and prevention of reflection and serialization
2022-07-24 00:48:00 【Handsome yuppie】
The singleton pattern
Pattern motivation
For some classes in the system , Only one example is important , For example, there is only one timing tool and ID( Serial number ) generator .
The application of singleton mode includes : The system only needs one instance object ; Only one common access point is allowed for a single instance of a client call class .
Definition
seeing the name of a thing one thinks of its function , Used to ensure that only one instance of an object can be created , besides , It also provides global access to instances .
There are three main points of the singleton model : First, a class can only have one instance ; Second, it must create this instance by itself ; Third, it must provide the whole system with this instance by itself .
Realization
To ensure the uniqueness of the singleton instance , be-all Singleton constructors are declared private Of , Re adoption statement Static method to achieve global access The singleton instance .
Slacker type
public class Singleton {
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null)
instance = new Singleton();
return instance;
}
public void doAction(){
//TODO Achieve what you need to do
}
}
Slacker type , As the name suggests, an instance is created only when it is used ,“ Compare the lazy ”, Check whether there are instances when using , Return if any , If not, build a new one . There are two ways to write thread safe and thread unsafe , The difference is synchronized keyword .
Hungry Chinese style
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton(){
}
public static Singleton getInstance(){
return instance;
}
public void doAction(){
//TODO Achieve what you need to do
}
}
Hungry Chinese style , It's also easy to understand from the name , Namely “ Relatively diligent ”, Examples are in initialization It's already built by the time of , Whether you use it or not , It's all built first . The advantage is No thread safety issues ( The class loading mechanism is used to avoid the problem of multithreading synchronization ), The downside is a waste of memory space .
Double check lock (Double Check)( recommend )
public class Singleton {
private volatile static Singleton instance = null;
private Singleton(){
}
public static Singleton getInstance(){
if(instance == null)
synchronized (Singleton.class){
if(instance == null)
instance = new Singleton();
}
return instance;
}
public void doAction(){
//TODO Achieve what you need to do
}
}
advantage :
- Thread safety
- Realization Lazy loading
- More efficient
principle :
1、 first if Verification is for Improve code execution efficiency , Because the singleton mode only needs to create an instance once , So when the instance is created , Call again getInstance Method does not have to compete for the synchronized code block , Simply return to the previously created instance .
2、 the second if Verification is for Prevent secondary instance creation . Because for the first time if Verification is not synchronized , It is possible that multiple threads have entered the first if There are competing resources , If there is no second verification , t1,t2 Are competing for synchronization resources ,t2 After getting the resources , Create examples , Then the resources are released ,t1 Get resources , t1 An instance will also be created , that , Multiple instances will be created , therefore , The second time if Check OK Completely avoid the problem of creating multiple instances caused by multithreading .
private volatile static Singleton instance = null; there
volatileessential ,volatileKeywords can avoid JVM Instruction rearrangement optimization .because instance = new Singleton(); It can be divided into three steps :
- by singleton Allocate memory space ;
- initialization singleton;
- take singleton Point to allocated memory space ;
But because of JVM It has the property of instruction reordering , The execution order may change to 1-3-2. Instruction reordering does not cause problems in a single thread , But in Multithreading will cause the thread to obtain an uninitialized instance . for example : Threads T1 Yes 1 and 3, here T2 call getInstance() After the discovery singleton Not empty , Therefore return singleton, But at this time singleton It's not initialized yet .
UsevolatileIt will be banned JVM Command rearrangement , So as to ensure the normal execution under multithreading .
Static inner class ( recommend )
public class Singleton {
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
public void doAction(){
//TODO Achieve what you need to do
}
}
This method uses the class loading mechanism to ensure that there is only one thread when initializing the instance , Static inner class in Singleton When loaded, it is not instanced immediately , It's calling getInstance() Static inner classes will be loaded only when , To complete the Singleton Instantiation . Because the static properties of the class will only be initialized when the class is loaded for the first time , Just through JVM The thread safety feature when loading classes ensures thread safety . There may also be reflection attacks or deserialization attacks .
advantage :
- utilize JVM The mechanism of loading static internal classes ensures multithreading safety
- Realization Lazy loading effect
- Efficient
Enumeration implementation ( recommend )
public enum Singleton {
INSTANCE;
public void doSomething() {
System.out.println("doSomething");
}
}
Automatic support for serialization mechanism , Absolutely prevent multiple instantiations .
advantage :
- Thread safety ( The creation of enumeration instances is thread safe by default )
- Prevent reflection , Destruction of singleton by cloning and serialization
Three ways of ring breaking single case mode : Reflection , serialize , clone
With Double Check As an example , Test reflection , serialize , Whether cloning can break the ring singleton mode :
public class Singleton implements Serializable,Cloneable {
private static volatile Singleton singleton;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
The test case :
public static void main(String[] args) throws Exception {
Singleton instance = Singleton.getInstance();
System.out.println(" The original singleton Of hashcode: " + instance.hashCode());
// Reflection
Constructor<Singleton> declaredConstructor = Singleton.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
Singleton singleton = declaredConstructor.newInstance();
System.out.println(" Reflection gets singleton Of hashcode: " + singleton.hashCode());
// clone
Singleton clone = (Singleton) Singleton.getInstance().clone();
System.out.println(" Clone obtained singleton Of hashcode: " + clone.hashCode());
// serialize
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(Singleton.getInstance());
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Singleton serialize = (Singleton) ois.readObject();
// Close the resource
System.out.println(" Serialize the obtained singleton Of hashCode: "+ serialize.hashCode());
}
Output results :
The original singleton Of hashcode: 460141958
Reflection gets singleton Of hashcode: 1163157884
Clone obtained singleton Of hashcode: 1956725890
Serialize the obtained singleton Of hashCode: 666641942
The operation results show that getInstance()、 Reflection 、 clone 、 Serialize these four ways to get Singleton Object's hashCode It's different , At this time, the singleton mode has been broken
How to prevent reflection 、 clone 、 Serialize the broken loop of the singleton pattern
1、 Prevent reflection from breaking the ring ( Although the construction method has been privatized , But using the reflection mechanism newInstance() Method constructors can also be called ):
- First define a global variable switch
isFristCreateOn by default - Change its state to off state when it is loaded for the first time
2、 Prevent cloning from breaking the ring
- rewrite
clone(), Returns the singleton object directly
3、 Prevent serialization from breaking the ring
- add to
readResolve(), returnObjectobject
public class Singleton implements Serializable, Cloneable {
private static final long serialVersionUID = 6125990676610180062L;
private volatile static Singleton singleton;
private static boolean isFristCreate = true;// The default is to create for the first time
private Singleton() {
if (isFristCreate) {
synchronized (Singleton.class) {
if (isFristCreate) {
isFristCreate = false;
}
}
} else {
throw new RuntimeException(" Has been instantiated once , Can no longer instantiate ");
}
}
public void doAction() {
//TODO Achieve what you need to do
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
@Override
protected Singleton clone() throws CloneNotSupportedException {
return singleton;
}
private Object readResolve() {
return singleton;
}
}
The test case :
public static void main(String[] args) throws Exception {
Singleton instance = Singleton.getInstance();
System.out.println(" The original singleton Of hashcode: " + instance.hashCode());
// clone
Singleton clone = (Singleton) Singleton.getInstance().clone();
System.out.println(" Clone obtained singleton Of hashcode: " + clone.hashCode());
// serialize
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(Singleton.getInstance());
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Singleton serialize = (Singleton) ois.readObject();
// Close the resource
System.out.println(" Serialize the obtained singleton Of hashCode: "+ serialize.hashCode());
// Reflection
Constructor<Singleton> declaredConstructor = Singleton.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
Singleton singleton = declaredConstructor.newInstance();
System.out.println(" Reflection gets singleton Of hashcode: " + singleton.hashCode());
}
test result :
The original singleton Of hashcode: 460141958
Clone obtained singleton Of hashcode: 460141958
Serialize the obtained singleton Of hashCode: 460141958
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at pc.TestSingleton.main(TestSingleton.java:37)
Caused by: java.lang.RuntimeException: Has been instantiated once , Can no longer instantiate
at pc.Singleton.<init>(Singleton.java:24)
... 5 more
Related articles
[1] Five ways to write singleton mode _absolute_chen The blog of -CSDN Blog _ The singleton pattern
[3] The implementation of singleton mode and how to effectively prevent reflection and deserialization - Call me Lord Peng - Blog Garden (cnblogs.com) ( recommend )
边栏推荐
- Redis | very important Middleware
- The salary of a tester who has worked for 3 years after job hopping is twice that of the original. The secret is
- 工作3年的测试员跳槽后工资是原来的2倍,秘诀原来是......
- Detailed overview of data standards -2022
- Summary of pit websocket
- 采坑websocket總結
- An article teaches you the basic use of kubernetes
- Implementation of singleton mode in C #
- MySQL之数据查询(SELECT)
- Educational Codeforces Round 132 (Rated for Div. 2) D. Rorororobot
猜你喜欢

Printf function - conversion description

Classic example of C language - print the input two digits in reverse order

Codeforces Round #807 (Div. 2)(A-D)

High number_ Chapter 2 differential calculus of multivariate functions__ Geometric application of partial derivatives_ Tangent and normal plane of space curve

Testers who have been employed for 3 months are facing employment confirmation. Leaders: 1 year of work experience is packaged into 5 years, and the probation period is eliminated

EFCore高级Saas系统下单DbContext如何支持不同数据库的迁移

Classic example of C language - find the minimum number of banknotes

Detectron2 installation based on Anaconda under win10

Classic example of C language - loan balance

Fpga:ov7725 camera displays images in rgb565 format through vga/hdmi
随机推荐
Flutter | the easiest way to add header and footer to listview
Method of C language annotation
Database connection pool & dbutils
[video game training] non contact object size and shape measurement 2020 video game G
SAP 实施项目中涉及到编程方式操作 Excel 的几种场景介绍
An article teaches you the basic use of kubernetes
MySQL table field quantity limit and row size limit
Redis | very important Middleware
First knowledge of C language functions
Notes and Thoughts on the red dust of the sky (VI) due to lack
网络系统实验:ping不通的问题解决
Bean validation custom container validation chapter ----06
Gbase 8C access authority query function (II)
Accelerating matrix vector multiplication of special matrices with FFT
Introduction to several scenarios involving programming operation of Excel in SAP implementation project
Redis cluster hash sharding algorithm (slot location algorithm)
Flutter | firstwhere error reporting
PHP implements stripe subscription
Implementation of singleton mode in C #
Image processing 1:rgb888_ YCbCr444