是否可以使用JVM字节码显式释放内存?

时间:2014-02-12 15:53:18

标签: compiler-construction jvm interpreter bytecode

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

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

3 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:2)

JVM的一个绝对原则是,对象绝对可以保证至少与对它们的任何引用一样长。如果组中的对象保持对彼此的强引用,但组中对它们的唯一引用被封装在WeakReference对象中,则组中的所有对象以及对它们的所有引用将不再存在,同时(WeakReference对象可能继续存在,但他们不再拥有对任何东西的引用。)

这样做的结果是,除非或直到JVM确定不存在对它的引用,否则不能重用对象的内存。因为确保一个特定对象不存在引用所需要的时间差不多,因为它需要对所有年龄相同或更新的对象执行垃圾收集,所以尝试并没有什么好处尽快回收记忆。如果考虑GC在需要内存时运行,则尤其如此。在需要记忆之前,没有任何好处可以释放它。

答案 2 :(得分:0)

两年后,当我发现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用来为实例创建分配内存。