jvm 是否可以完成/发布类示例?

xj3cbfub  于 2022-11-07  发布在  其他
关注(0)|答案(1)|浏览(111)

这可能是因为我用错了关键词,没有太多的讨论或文章发现这个问题。
加载到JVM后,是否可以自动或手动释放一个Class示例?

  • 如果可以自动放行,这个程序什么时候执行?我们能期待一个时间点吗?
  • 如果可以手工发布,怎么发布?有没有一些API?
  • 如果它可以自动或手动释放,我们是否能够监控Class示例的终结,即使使用JVM之外的一些外部工具?

有些旧文章说,如果

  • 没有对Class的任何示例/静态成员的引用
  • 释放其ClassLoader示例

Class将被发布。它是否适用于最新的JVM(例如,Oracle VM 17或GraalVM 17)?这是否意味着我们能够构建一些Class以供即时使用,而不必担心内存泄漏?

  1. class CustomClassLoader extends java.lang.ClassLoader
  2. {
  3. public CustomClassLoader()
  4. {
  5. super(CustomClassLoader.class.getClassLoader());
  6. }
  7. public Class<?> loadBytes(byte[] bytecode)
  8. {
  9. return defineClass(null, bytecode, 0, bytecode.length);
  10. }
  11. }
  12. @SneakyThrows
  13. Object testMethod()
  14. {
  15. // read a Class from bytecode by a local ClassLoader
  16. byte[] bytecode = readSomeBytesFromSomewhere();
  17. var cl = new CustomClassLoader();
  18. Class<?> classTest = cl.loadBytes(bytecode);
  19. // any random code
  20. return classTest.getMethod("testMethodInClass").invoke(null);
  21. }
  22. public static void main(String... args)
  23. {
  24. for(int step = 0; step < 9999; step++)
  25. testMethod();
  26. }

对于上面的代码,我们是否可以认为每次testMethod完成时,classTest使用的任何资源都会被释放,因为它的ClassLoader局部变量cl从未被再次使用过?

wi3ka0sx

wi3ka0sx1#

对于上面的代码,我们是否可以认为每次testMethod完成时,classTest使用的任何资源都会被释放,因为它的ClassLoader局部变量cl从未被再次使用?
不,但我认为你在这里混淆了术语。特别是,任何资源,不。资源有一个非常具体的含义。它有必要被释放吗?不。再次,具体的含义。
所以让我试着具体一点:
释放?我想你是说收藏
如果由cl.loadBytes创建的对象是可垃圾回收的(从上面的代码可以看出,它是可垃圾回收的),它的所有示例都是可垃圾回收的(在您的示例中是平凡的;您没有创建示例),并且ClassLoader对象是可收集的(同样,在您的代码中,它是可收集的),那么,也只有到那时,它才是可收集的。
这是否意味着它会立即消失?不,这不是垃圾收集器的工作方式。如果收集器认为有必要这样做,它就会进行垃圾收集。如果收集器认为没有必要这样做,它就不会这样做。这对你来说无关紧要--垃圾仅仅存在是没有影响的。
关键是,JVM不会抛出OutOfMemoryError,因为有10,000个Class对象的副本填满了内存。
“释放”是一个只在官方用语中用于表示资源的词。见下一节。
资源?我想您是指对象
资源是代表操作系统/架构级别概念的任何对象,* 因此必须手动关闭 * 该对象,释放该资源。
“resource”的一个例子是new FileInputStream。这是一个资源对象--你不需要依靠垃圾收集器来清理它,因为垃圾收集器可以自由地决定这个特定的对象在5天后是否需要清理。如果有足够的堆,为什么要这么做呢?这不是学术上的--这种情况真的会发生。因此,不要,永远不要,不使用try-with-resources打开资源对象(或者将它们加载到一个本身为implements AutoClosable的对象中,这样代码的用户就可以这样做)。这是唯一安全的方法。
这就是所谓的“释放”。
你问的是关于资源和释放资源的问题,就像枪和奶奶一样:一点也不。
如果要使用资源,请使用try-with:

  1. // bad:
  2. void foo() throws IOException {
  3. var in = new FileInputStream(...);
  4. // do stuff with 'in'
  5. in.close();
  6. }
  7. // good:
  8. void foo() throws IOException {
  9. try (var in = new FileInputStream(...)) {
  10. // do stuff with 'in
  11. }
  12. }

类加载器的恶作剧根本不会改变这一点。不使用try-with或手动推出try/finally循环,就不可能“自动释放”资源。

展开查看全部

相关问题