单例模式和静态对象的销毁

EnjoySilence 2013-08-09 02:09:59
场景描述:
1.为某软件做了一个扩展功能的插件,插件可以随时被加载或删除,而不影响软件本身的运行;
2.插件中定义了一个单例的类,也就是说,这个类的存在唯一一个静态对象,这个静态对象在插件被加载时生成;
3.这个单例类的构造器中启动了一个维护线程;
4.在第一次加载插件时,单例类的唯一静态对象被创建,调用构造器时启动了维护线程;
5.删除插件,插件的删除代码中关闭了之前开启的那个维护线程,但此时单例类的静态对象依旧存在;
6.再次加载插件,因为之前插件中的单例类对象依旧存在,所以不会调用单例类的构造器,也不会启动维护线程。

如上描述,因为单例模式的原因,不能每次加载插件时都启动维护线程,要解决这个问题,只能每次都重启该软
件本身,但这不太实际,因为软件是必须一直运行的。

所以问题归结到:
能不能在删除插件时销毁其单例类的静态对象?或者更宽泛些,怎样手工销毁静态对象?
...全文
1961 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
EnjoySilence 2013-08-12
  • 打赏
  • 举报
回复
感谢各位指教,但最后因为考虑到效率和其它方面的原因,换了个实现方式。 新手分不多,没有拿到的分朋友见谅。
EnjoySilence 2013-08-12
  • 打赏
  • 举报
回复
引用 19 楼 tcmakebest 的回复:
不就是线程的问题吗,为什么不能设个标记,如果已经退出就再开一次,问题不就解决了
关键问题在于这个类只被加载了一次,插件删除时,静态对象还是存在的,如果此时关闭线程,等下次再开启插件时,并不能再生成一个静态对象,也就不会重新运行这个线程了。
tcmakebest 2013-08-11
  • 打赏
  • 举报
回复
不就是线程的问题吗,为什么不能设个标记,如果已经退出就再开一次,问题不就解决了
悠扬-tiger 2013-08-10
  • 打赏
  • 举报
回复
单例模式的主要作用是用来记录对象的状态的,在对象中设置一个状态的变量,关闭线程的时候,将状态变为不可用状态,开启的时候置为可用状态,这样就不必销毁静态对象了。
马达马达达 2013-08-10
  • 打赏
  • 举报
回复
引用 6 楼 beowulf2005 的回复:
置null是一个办法。 但是没解决根本性问题,因为类未被卸载。 事实上类的卸载根本不由你控制。 假设你改了一个BUG,类名没有变, 你删除当前插件,然后马上安装新插件, 结果往往是调来的还是老插件,因为原来的类没被卸载。 通常解决的办法是用classloader,但这依赖与母程序的构架设计。 情况往往是很复杂的。 要实现或者学习热插件系统, 可以参看OSGi规范,以及他的开源实现。 eclipse就是这个构架。 个人觉得,Hadson 也是一个比较好的热插件系统范例, 可以看看Hudson源码。
+1 学习了
阚雷--闞靁 2013-08-10
  • 打赏
  • 举报
回复
在单例类里加个public方法把这个静态实例变量赋值为null
JRockit 2013-08-10
  • 打赏
  • 举报
回复
引用 14 楼 EnjoySilence 的回复:
[quote=引用 9 楼 gaobaiy 的回复:] 重新为你的插件写一个专职的ClassLoader, http://vivisidea.iteye.com/blog/662620
Good Idea. 但最终还是要把引用置为null吧?有可以直接调用的方法来显示unload一个class吗?[/quote] 这个不需要,判断两个类是否相等只有在这两个类是被同一个类加载器加载的情况下才有意义,假如两个不同的类加载器加载的是同一个class文件,那么这两个类也不相等,所以个人认为,当你的插件卸载之后再部署,前后运行的这两个单例类并不相等,因为他们的类加载器并不相等。
EnjoySilence 2013-08-10
  • 打赏
  • 举报
回复
引用 9 楼 gaobaiy 的回复:
重新为你的插件写一个专职的ClassLoader, http://vivisidea.iteye.com/blog/662620
Good Idea. 但最终还是要把引用置为null吧?有可以直接调用的方法来显示unload一个class吗?
joyment2010 2013-08-10
  • 打赏
  • 举报
回复
EnjoySilence 2013-08-10
  • 打赏
  • 举报
回复
引用 3 楼 e274794140 的回复:
额,在单例类里加个public方法把这个静态实例变量赋值为null是不是就行了
这个方法只适用于类似下面的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; } }
gaobaiy 2013-08-09
  • 打赏
  • 举报
回复
重新为你的插件写一个专职的ClassLoader, http://vivisidea.iteye.com/blog/662620
raistlic 2013-08-09
  • 打赏
  • 举报
回复 1
简单的 null 掉那个单例的实例,并不能释放 plugin 加载的静态资源。 并且也排除了依赖类的加载来又“安全”又“懒”的进行实例化的可能。
raistlic 2013-08-09
  • 打赏
  • 举报
回复
类的卸载问题。 楼上 +1 这个没做过,不过据说一个类被“卸载”的条件是,加载它的 ClassLoader 被回收。 一般 plugin 里的类需要“看到”软件里的类型,所以这个 ClassLoader 一般其 parent 为软件主体的 ClassLoader 设计上要注意,软件主体中的任何类型是“看不到” plugin 那一层加载的类型的,所以软件主体中任何部分不能提到plugin那一层加载的类型。 同一个程序下分级的ClassLoader有很多隐患,有些第三方的库因为自身的设计问题可能会“越级”加载类型而导致出错,比如 Jasper Report
beowulf2005 2013-08-09
  • 打赏
  • 举报
回复
置null是一个办法。 但是没解决根本性问题,因为类未被卸载。 事实上类的卸载根本不由你控制。 假设你改了一个BUG,类名没有变, 你删除当前插件,然后马上安装新插件, 结果往往是调来的还是老插件,因为原来的类没被卸载。 通常解决的办法是用classloader,但这依赖与母程序的构架设计。 情况往往是很复杂的。 要实现或者学习热插件系统, 可以参看OSGi规范,以及他的开源实现。 eclipse就是这个构架。 个人觉得,Hadson 也是一个比较好的热插件系统范例, 可以看看Hudson源码。
西电小楠 2013-08-09
  • 打赏
  • 举报
回复
引用 3 楼 e274794140 的回复:
额,在单例类里加个public方法把这个静态实例变量赋值为null是不是就行了
目测好答案
gaobaiy 2013-08-09
  • 打赏
  • 举报
回复
引用 3 楼 e274794140 的回复:
额,在单例类里加个public方法把这个静态实例变量赋值为null是不是就行了
是啊,你关掉维护线程的同时,将单例对象=null
马达马达达 2013-08-09
  • 打赏
  • 举报
回复
额,在单例类里加个public方法把这个静态实例变量赋值为null是不是就行了
懷念那回憶 2013-08-09
  • 打赏
  • 举报
回复
帮顶,顺带学习,等大仙赐教,
S117 2013-08-09
  • 打赏
  • 举报
回复
把那个类从JVM中卸载了

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧