场景描述:
1.为某软件做了一个扩展功能的插件,插件可以随时被加载或删除,而不影响软件本身的运行;
2.插件中定义了一个单例的类,也就是说,这个类的存在唯一一个静态对象,这个静态对象在插件被加载时生成;
3.这个单例类的构造器中启动了一个维护线程;
4.在第一次加载插件时,单例类的唯一静态对象被创建,调用构造器时启动了维护线程;
5.删除插件,插件的删除代码中关闭了之前开启的那个维护线程,但此时单例类的静态对象依旧存在;
6.再次加载插件,因为之前插件中的单例类对象依旧存在,所以不会调用单例类的构造器,也不会启动维护线程。如上描述,因为单例模式的原因,不能每次加载插件时都启动维护线程,要解决这个问题,只能每次都重启该软
件本身,但这不太实际,因为软件是必须一直运行的。所以问题归结到:
能不能在删除插件时销毁其单例类的静态对象?或者更宽泛些,怎样手工销毁静态对象?多线程单例模式静态对象
1.为某软件做了一个扩展功能的插件,插件可以随时被加载或删除,而不影响软件本身的运行;
2.插件中定义了一个单例的类,也就是说,这个类的存在唯一一个静态对象,这个静态对象在插件被加载时生成;
3.这个单例类的构造器中启动了一个维护线程;
4.在第一次加载插件时,单例类的唯一静态对象被创建,调用构造器时启动了维护线程;
5.删除插件,插件的删除代码中关闭了之前开启的那个维护线程,但此时单例类的静态对象依旧存在;
6.再次加载插件,因为之前插件中的单例类对象依旧存在,所以不会调用单例类的构造器,也不会启动维护线程。如上描述,因为单例模式的原因,不能每次加载插件时都启动维护线程,要解决这个问题,只能每次都重启该软
件本身,但这不太实际,因为软件是必须一直运行的。所以问题归结到:
能不能在删除插件时销毁其单例类的静态对象?或者更宽泛些,怎样手工销毁静态对象?多线程单例模式静态对象
但是没解决根本性问题,因为类未被卸载。
事实上类的卸载根本不由你控制。假设你改了一个BUG,类名没有变,
你删除当前插件,然后马上安装新插件,
结果往往是调来的还是老插件,因为原来的类没被卸载。
通常解决的办法是用classloader,但这依赖与母程序的构架设计。
情况往往是很复杂的。要实现或者学习热插件系统,
可以参看OSGi规范,以及他的开源实现。
eclipse就是这个构架。个人觉得,Hadson 也是一个比较好的热插件系统范例,
可以看看Hudson源码。
http://vivisidea.iteye.com/blog/662620
这个方法只适用于类似下面的Singleton实现方式:class Singleton {
private static Singleton instance = null; // 重点,此处不为null就不可用
private Singleton() {
System.out.println("Constructing a Singleton object.");
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public static synchronized void dstroyInstance() {
if (instance != null) instance = null;
}
}
Good Idea. 但最终还是要把引用置为null吧?有可以直接调用的方法来显示unload一个class吗?
Good Idea. 但最终还是要把引用置为null吧?有可以直接调用的方法来显示unload一个class吗?
这个不需要,判断两个类是否相等只有在这两个类是被同一个类加载器加载的情况下才有意义,假如两个不同的类加载器加载的是同一个class文件,那么这两个类也不相等,所以个人认为,当你的插件卸载之后再部署,前后运行的这两个单例类并不相等,因为他们的类加载器并不相等。