我研究了许多不同类型的代码片段,可以将它们插入您的注释所在的位置,并且唯一不会导致的
OutOfMemoryError代码类型是将一些值分配给局部变量的代码。
这是对我来说最有意义的解释:
当你有
byte[] data = new byte[dataSize];
该字节码指令是
12: newarray byte 14: astore_1
在哪里
newarray创建一个新数组并将
astore_1对它的引用存储在局部变量1。
此后,该变量的作用域丢失,但是字节码没有说明清除其值的任何内容,因此在堆栈帧中保留了对该对象的引用。即使代码本身无法达到此特定的垃圾收集器,它也可以实现。
如果相反,您尝试分配另一个局部变量,例如
byte i = 1;
那么相应的字节码指令就像
15: iconst_1 16: istore_1
其中
iconst_1将值1存储在堆栈上,并将
istore_1该值存储在变量1中,该变量似乎与以前相同。如果是,则您将覆盖它的值,对该
byte[]对象的引用将丢失,然后该对象“成为”有资格进行垃圾回收。
最终证明
使用
-g选项编译此代码
public class Driver { private static final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6); public static void main(String[] args) throws InterruptedException { { System.out.println(dataSize); byte[] data = new byte[dataSize]; } byte i = 1; System.out.println(dataSize); byte[] data2 = new byte[dataSize]; }}
然后运行
javap -c -l Driver。你会看到
LocalVariableTable这样的
LocalVariableTable: Start Length Slot Name Signature 15 0 1 data [B 0 33 0 args [Ljava/lang/String; 17 16 1 i B 32 1 2 data2 [B
其中槽是在索引中
astore_1和
istore_1。因此,
byte[]当您为局部变量分配新值时,对的引用将被清除。即使变量具有不同的类型/名称,它们也以字节码形式存储在同一位置。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)