我目前想知道JVM中的实际开销是用于加载从未使用过的额外类。
我们有代码迭代类路径中的所有类,以查找实现某个接口的类,然后加载它们。
这允许将自定义类简单地放在目录中,然后加载并注册它们。
副作用是我们命中了类路径中的每个类,导致加载类。对JVM内存有什么影响?
简单地加载类会对内存产生多大影响吗?
答案 0 :(得分:4)
像往常一样,我建议根据您的具体情况进行测量。
话虽如此,我不确定我是否建议扫描整个类路径。如果您不控制类路径(它是您的客户或类似路径),他们可能会向其添加任何内容,并且您的流程将扫描他们放入类路径的任何内容(可能与您的应用无关)。
我建议你只提名可以上传类的某些目录/存储库,这样你就可以限制类路径扫描并减少无意中拾取你不想要的东西的机会。
答案 1 :(得分:2)
如果您使用单独的ClassLoader来加载这些类并且very careful不创建对这些类或它们的实例的任何引用,那么当ClassLoader符合垃圾收集条件时,类也是如此。
因此,您可以通过使用单独的ClassLoader进行2次传递来避免不必要地堵塞PermGen空间:一个用于加载所有类并标识要保留的类,另一个用于实际使用它们。
答案 2 :(得分:1)
不会以这种方式使用ClassLoaders会产生意想不到的副作用吗?就像运行静态初始化程序一样。
您可以使用ServiceLoader机制,但如果不适合,您可以在不使用ClassLoaders的情况下检查类 - BCEL和ASM等字节操作库可以用于检查课程。
答案 3 :(得分:0)
是的,这会强制VM加载类文件并检查它(这可能是性能问题)。此外,如果您使用的是Sun VM,那么这些类将永远保留在内存中。 Sun VM将类放在所谓的“PermGen”空间中,除非您指定了特殊选项,否则永远不会进行垃圾回收。
所以这通常是一个坏主意,但有两个简单的解决方法:
检查班级名称(文件名)。在名称中重复界面名称,这样您就可以轻松注意到要加载的内容以及不加载的内容。
使用两个目录。一个包含普通类,另一个包含您希望始终加载的类。
答案 4 :(得分:0)
“远在那里”的建议:
你可以做同样的事情,但没有实际使用VM吗?记录了类文件规范,难道你不能编写自己的应用程序来读取类文件,并确定它们是否实现了你的接口/没有实际加载它们?
这将使您能够扫描任何目录,但无需担心加载类或静态初始化器或类似的东西。