tomcat - 动态重新加载类
我有一个包含很多 .class 文件的文件夹。该类是从'app 1'更新的。并且有'app 2'动态加载这些类。
问题是......
'app 2'使用类文件,'app 1'更新该文件,然后'app 2' > 再次需要该类,但它似乎保留并使用旧类的副本。
因此,我检查了文件夹并且类已成功更新,我尝试重新加载 'app 2' 但它继续使用旧的类。
仅当我重新启动 tomcat 'app 2' 时才会读取新类。
这是为什么? 我可以重新加载'app 2',但是在生产环境中,我无法重新启动tomcat。
它对我的工作非常重要,我很欣赏任何想法......
我正在使用 tomcat6 的全新安装,并使用以下命令加载类文件: Class.forName(
非常感谢
I have a folder with a lot of .class files. This classes are updated from 'app 1'. And there is 'app 2' that loads those classes dinamically.
And the problem is....
'app 2' uses a class file, 'app 1' update that file, then 'app 2' needs again the class but it seemes to keep and to use a copy of the older class.
so, I checked the folder and the class was updated successfully, I tried to reload 'app 2' but it keeps using the older class.
Only if I restart tomcat 'app 2' reads the new class.
Why is that?
I'm allowed to reload 'app 2' but, in production enviroment, I cant restart tomcat.
Its very important in my job, I appreciate any idea.....
I'm using a clean installation of tomcat6 and I load the class files with:Class.forName(<classname>).newInstance()
thx a lot
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题是运行时已经将旧的类文件加载到想要使用修改后的类的代码所使用的类加载器中。您必须找到一种方法让类加载器从磁盘刷新其类内容才能实现您想要的效果。这就是 Class.forName() 不起作用的原因:它正在访问类的已加载(和缓存)版本。 Alex R 是对的,您应该尝试重组代码以分离这两个项目的类。但是,如果您执意要尝试重新加载该类并保持原样,您可以尝试使用 Classloader.defineClass() 进行实验,并将该类的新版本从其 .class 文件加载到 byte[] 中,然后将该 byte[] 传递给 Classloader.defineClass()。您很可能希望使用 Tomcat 与您的应用程序关联的上下文类加载器(而不是顶级 Tomcat 类加载器)。 Tomcat 项目文档中有区分这两者的文档。
The problem is that the runtime has already loaded the old classfile into the classloader being used by the code that wants to use the modified class. You'd have to find a way to get the classloader to refresh its class contents from disk in order to achieve what you want. This is why Class.forName() isn't working : it's accessing the already loaded (and cached) version of the class. Alex R is right that you should try to restructure your code to separate your classes for these two projects. But, if you're dead set on trying to reload that class and keep things they way they are, you can try experimenting with Classloader.defineClass() and loading the new version of the class from its .class File into a byte[], then passing that byte[] to Classloader.defineClass(). You'll most likely want to use the context classloader associated with your application by Tomcat (rather than the top level Tomcat classloader). There's documentation distinguishing between the two in the Tomcat project documentation.
默认行为是类由加载它们的
ClassLoader
进行缓存。如果连续两次执行:Class.forName('MyClass')
,则只会在第一次加载该类。要重新加载类,您不仅需要释放对该类的任何实例的所有引用,还需要释放对加载该类的
ClassLoader
的所有引用。只有这样你才能确定整个类可以被垃圾收集(否则你最终会遇到内存泄漏——重新加载 web 应用程序时的一个长期问题)。您也许能够扩展
ClassLoader
并改变缓存行为。Default behaviour is that classes are cached by the
ClassLoader
that loaded them. If you do:Class.forName('MyClass')
two times in a row, you will only load the class the first time.To reload a class, you need not only to release any reference you already have to any instance of this class, but also any reference you have to the
ClassLoader
that loaded it. Only then can you be sure the whole class can be garbage collected (or you will end up with memory leaks - a perennial problem in reloading webapps).You may be able to extends
ClassLoader
and alter the caching behaviour.你是对的!
这是关于 Alex 想法的一个很好的解释
You are right!
This is a great explanation with an example about Alex´s idea
我认为你应该尝试将这两个应用程序的类分开。首先尝试创建 2 个相同的目录。一个用于 app1,第二个用于 app2。如果这解决了您的问题,请将您的类打包到 jar 中,并仅保留 2 个重复的 jar 文件。我认为问题不在于java,而在于文件系统。我相信你用的是windows。如果是这样,可能会尝试做你现在在 Linux 中所做的事情(除非它与你的公司无关)。
I think that you should try to separate classes for these 2 applications. Try first to create 2 identical directories. One for app1, second for app2. If this solves your problem pack your classes into jar and keep just 2 duplicate jar files. I think that the problem is not in java but in filesystem. I believe that you are using windows. If so probably try to do what you are doing now in linux (unless it is irrelevant for your company).