我有一个包含很多.class文件的文件夹。此类已从'app 1'更新。还有'app 2'可以加载这些类。
问题是......
'app 2'使用类文件,'app 1'更新该文件,然后'app 2'再次需要该类但它保留并使用旧班的副本。
所以,我检查了文件夹并且课程已成功更新,我尝试重新加载'app 2',但它继续使用较旧的课程。
只有重新启动tomcat 'app 2'才会读取新类。
为什么? 我被允许重新加载'app 2'但是,在生产环境中,我无法重新启动tomcat。
在我的工作中非常重要,我很欣赏任何想法......
我正在使用tomcat6的干净安装,我加载了类文件:
Class.forName(<classname>).newInstance()
答案 0 :(得分:3)
问题是运行时已经将旧的类文件加载到想要使用修改后的类的代码所使用的类加载器中。你必须找到一种方法让类加载器从磁盘刷新它的类内容,以实现你想要的。这就是Class.forName()不起作用的原因:它正在访问类的已加载(和缓存)版本。 Alex R是对的,您应该尝试重构代码以分离这两个项目的类。但是,如果您试图重新加载该类并按照它们的方式保留它们,那么您可以尝试使用Classloader.defineClass()并将该类的新版本从其.class文件加载到byte []中,然后将该byte []传递给Classloader.defineClass()。您很可能希望使用Tomcat与您的应用程序关联的上下文类加载器(而不是顶级Tomcat类加载器)。这些文档在Tomcat项目文档中区分了两者。
答案 1 :(得分:2)
默认行为是类加载它们的ClassLoader
缓存。如果您连续两次执行:Class.forName('MyClass')
,则只会在第一次加载该类。
要重新加载一个类,您不仅需要释放已经具有此类的任何实例的任何引用,还需要对加载它的ClassLoader
进行任何引用。只有这样你才能确定整个类都可以被垃圾收集(或者你最终会遇到内存泄漏 - 重新加载webapps时会出现长期存在的问题)。
您可能能够扩展ClassLoader
并改变缓存行为。
答案 2 :(得分:1)
答案 3 :(得分:0)
我认为您应该尝试为这两个应用程序分隔类。首先尝试创建2个相同的目录。一个用于app1,第二个用于app2。如果这解决了您的问题,请将您的类打包到jar中,并保留2个重复的jar文件。我认为这个问题不是在java中,而是在文件系统中。我相信你正在使用Windows。如果是这样,可能会尝试在linux中做你现在正在做的事情(除非它与你的公司无关)。