【问题标题】:Is it possible to explicitly free memory with JVM Bytecode?是否可以使用 JVM 字节码显式释放内存?
【发布时间】:2014-02-12 15:53:17
【问题描述】:

several computer programming languages 使用 JVM 字节码作为其解释器/编译器的目标语言。在我看来,许多新的编程语言(不到 15 年的历史)都在 JVM 上运行,我想知道是否所有这些语言都禁止显式内存释放:

是否可以通过任何指令在字节码中显式分配-解除分配内存?相反,垃圾收集器是否总是负责释放内存?

【问题讨论】:

    标签: compiler-construction jvm interpreter bytecode


    【解决方案1】:

    JVM 抽象出所有内存管理。没有用于内存释放的字节码,就像没有用于内存分配或直接内存访问的字节码一样。如果你想这样做,你必须直接或间接地使用本机代码。

    【讨论】:

    • 是的。您可以通过查看完整的字节码指令集来确认这一点docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html
    • 有一些指令为 'new' 或 'newarray' 隐式分配内存。我从您的回答和字节码指令集列表中了解到,没有“del”之类的东西。是否可以在本机代码中实现类似“del”指令,然后以字节码形式调用它?这样,您可以将假设的编程语言内存释放指令编译为字节码 + 您的小本机代码。
    • 没有任何用处。 “new”等的实现是依赖于实现的,所以即使你可以编写一个侵入堆的“del”,它也不是稳定的或可移植的。有 C 到字节码编译器。他们使用 java 数组模拟 malloc、free、指针算术等。
    • @pablo JVM 甚至不能保证为 new 或 newarray 分配内存,更不用说创建一个实际的堆对象了。这只是一个抽象。
    【解决方案2】:

    JVM 的绝对原则之一是绝对肯定地保证对象的持续时间至少与对它们的任何引用一样长。如果一个组中的对象相互持有强引用,但组外对它们的唯一引用封装在WeakReference 对象中,那么组中的所有对象以及对它们的所有引用将同时不复存在( WeakReference 对象可能会继续存在,但它们不会再持有对任何东西的引用)。

    这样做的结果是对象的内存不能被重用,除非或直到 JVM 可以确定不存在对它的引用。因为确保不存在对某个特定对象的引用所花费的时间与对大约相同或更新的所有对象执行垃圾收集所花费的时间差不多,所以尝试更快地回收内存确实没有任何好处.如果认为 GC 在需要内存时运行,则尤其如此。在需要内存之前,释放它没有任何好处。

    【讨论】:

      【解决方案3】:

      两年后,当我刚刚发现 Apache Spark 中的 project Tungsten 正在使用一种 hack 来使用 JVM 在堆中分配和取消分配内存时,我回到了这个问题。

      这不是新的,所以可以做到。您可以找到更多详细信息here 我从哪里得到以下示例:

      public DirectIntArray(long size) {
        startIndex = unsafe.allocateMemory(size * INT_SIZE_IN_BYTES);
        unsafe.setMemory(startIndex, size * INT_SIZE_IN_BYTES, (byte) 0);
        }
      }
      
      public void setValue(long index, int value) {
        unsafe.putInt(index(index), value);
      }
      
      public int getValue(long index) {
        return unsafe.getInt(index(index));
      }
      
      private long index(long offset) {
        return startIndex + offset * INT_SIZE_IN_BYTES;
      }
      
      public void destroy() {
        unsafe.freeMemory(startIndex);
      }
      

      GC 完全不知道以这种方式分配的内存。我称其为 hack,因为它使用代码反射来打开内部方法,这些方法只能由 ClassLoader 使用来为实例创建分配内存。

      【讨论】:

        猜你喜欢
        • 2012-05-07
        • 2011-01-12
        • 2017-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-19
        相关资源
        最近更新 更多