http://d.hatena.ne.jp/SiroKuro/20080403/1207236878
なんとなく気になったので、Singleton を破壊するための TIPS を余談として提示してみます。
結局クラスが一意であることを利用してクラスを1対1に結びついた単一のオブジェクトを作ってるだけなんだから
証明を書くには余白が足りない - 西尾泰和のはてなダイアリー
結局、クラスが一意じゃなければ、Singleton は破壊できちゃうんですよね。
今回破壊する Singleton はこういうクラスです。いたってシンプル。
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() { return instance; }
}
これを、こういうコードからロードしてみちゃったりします。だいぶ乱暴なことをしますね。
import java.io.*;
class test {
public static void main(String[] args) throws Exception {
System.out.println(newInstance() == newInstance());
}
private static Object newInstance() throws Exception {
File file = new File("Singleton.class");
final byte[] data = new byte[(int)file.length()];
new FileInputStream(file).read(data, 0, data.length);
return new ClassLoader() {
public Class<?> destroySingleton() {
return defineClass("Singleton", data, 0, data.length);
}
}.destroySingleton().getMethod("getInstance").invoke(null);
}
}
結果は "false"
defineClass のたびに、新しい Singleton クラスが返ってきます。
素人にはお勧めできない。
微妙にクラスが一意という条件は満たしていますが、1つのクラスファイルから複数個の Class をロードできる、という例でした。
追記
上記コードを
- private static Object newInstance() throws Exception {
+ private static Singleton newInstance() throws Exception {
- return new ClassLoader() {
+ return (Singleton) new ClassLoader() {
のように変更すると、もちろんコンパイルは通るんですが、実行すると
Exception in thread "main" java.lang.ClassCastException: Singleton cannot be cast to Singleton
at test.newInstance(test.java:10)
at test.main(test.java:4)
という、世にも奇妙な例外を吐き出してきます。
やっぱり素人にはお勧めできない。