以下代码是否对序列化和反射攻击都有抵抗力?
public class Example{
private static Example instance=new Example();
private Example(){}
public static Example getInstance(){
return instance;
}
}
答案 0 :(得分:8)
引用约书亚布洛赫的话,
从1.5版开始,还有第三个 实施单身人士的方法。 只需制作一个枚举类型 元素:
// Enum singleton - the preferred approach
public enum Elvis{
INSTANCE;
public void leaveTheBuilding(){...}
}
这种方法在功能上 相当于公共领域 方法,除了它更多 简洁,提供序列化 机械免费,提供 反对多重的铁定保证 实例化,即使面对 复杂的序列化或 反思攻击。
修改强>
如果你想知道为什么,Joshua Bloch说,
维持单身人士保证, 你必须声明所有实例字段
transient
并提供一个readResolve
方法。否则,每个 序列化实例的时间 反序列化,一个新的实例将是 创造了......
答案 1 :(得分:4)
不,不是。有一种更好的技术。
尝试这样的事情:
public enum Elvis {
INSTANCE;
public static boolean isThereOnlyOneElvis() {
return true;
}
}
// In your code:
if ( !Elvis.INSTANCE.isThereOnlyOneElvis() ) {
System.err.println("Liar !!!");
}
答案 2 :(得分:4)
由于您的Example类不可序列化,我想在这种情况下序列化不是问题。关于反思,如果有人用它来创建你的单身的另一个实例,那么他显然是恶意的IMO,并且无论如何都有可能在脚下射击自己。
答案 3 :(得分:2)
就反射而言,上下文中的单例不是反射证明。你可以使用setAccssible(true)来获取私有构造函数并实例化单例。您可以在 - 获取有关此事的更多详细信息 - http://technonstop.com/java-singleton-reflection-and-lazy-initialization
答案 4 :(得分:-1)
package com.eiq.singleton;
import java.io.Serializable;
public class SingleTonDemo implements Cloneable, Serializable {
// order of declaring variables objCount and SingleTonDemo should be same.
private static int objCount = 0;
private static SingleTonDemo obj = new SingleTonDemo();
//this value is not needed, to test whether the object value only, you can remove it, the code will work
int i = 10;
private SingleTonDemo() {
// logic to throw exception if we are trying to create object through reflection.
if (objCount == 0) {
synchronized (SingleTonDemo.class) {
if (objCount == 0)
objCount++;
}
} else {
throw new RuntimeException(
"Singleton class, Object creation is restricted");
}
}
public static SingleTonDemo getInstance() {
return obj;
}
// To avoid duplication
@Override
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException(
"Cannot Duplicate Single Ton Object");
}
// To avoid serialization and deserialization problems
public Object readResolve() {
return SingleTonDemo.getInstance();
}
}
In the above program will create only one object in all the cases like serialization, cloning, reflection and factory method etc.
This is the testing code:
package com.eiq.singleton;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
public class TestSingleTon {
private static final String FILE_PATH = "E:/suman/singleton.txt";
public static void main(String[] args) throws Exception {
System.out
.println("Creating through factory method of SingleTonDemo.getInstance()");
SingleTonDemo obj = SingleTonDemo.getInstance();
System.out.println(obj + " obj i=" + obj.i);
// Serializing the object
FileOutputStream fos = new FileOutputStream(FILE_PATH);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
System.out.println();
System.out.println("Object creation through deserialization mechanism");
// Returns the already created object if we trying to create object
// through Deserialization mechanism.
// Deserializing the object first time
FileInputStream fis1 = new FileInputStream(FILE_PATH);
ObjectInputStream ois1 = new ObjectInputStream(fis1);
SingleTonDemo deserializedObj1 = (SingleTonDemo) ois1.readObject();
System.out.println(deserializedObj1 + " deserializedObj1 i="
+ deserializedObj1.i);
// Deserializing the object second time, in both the case returns same
// object
FileInputStream fis2 = new FileInputStream(FILE_PATH);
ObjectInputStream ois2 = new ObjectInputStream(fis2);
SingleTonDemo deserializedObj2 = (SingleTonDemo) ois2.readObject();
System.out.println(deserializedObj2 + " deserializedObj2 i="
+ deserializedObj2.i);
// throws exception if we duplicate the object
// SingleTonDemo ob = (SingleTonDemo) obj.clone();
// Through Reflection
System.out.println();
System.out
.println("=====Throwing Exception if we are trying to create object through Reflection=======");
Class<SingleTonDemo> rObj = (Class<SingleTonDemo>) Class
.forName("com.eiq.singleton.SingleTonDemo");
Constructor<SingleTonDemo>[] constructors = (Constructor<SingleTonDemo>[]) rObj
.getDeclaredConstructors();
for (Constructor<SingleTonDemo> constructor : constructors) {
constructor.setAccessible(true);
SingleTonDemo reflObj1 = constructor.newInstance();
System.out.println(reflObj1 + " reflObj1 i=" + reflObj1.i);
}
}
}