发现Java虚拟机内存泄露问题

原创
开发 后端
内存泄露问题对于程序来说,是一个很难发现,并且容易引起严重灾害的事情。Java一直以其垃圾回收机制为自豪,那是否这种机制就是完美的呢。

常规理解上,Java的内存管理机制是将局部变量保存在堆中,当变量的作用域结束之后,该变量所占用的内容会被自动回收。不需要做任何特殊的处理。比如下面的代码:

  1. public class JavaMemory{  
  2.     private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);  
  3.     public void f(){  
  4.         {  
  5.             byte[] data1 = new byte[dataSize];  
  6.         }  
  7.         byte[] data2 = new byte[dataSize];  
  8.     }  
  9.  
  10.     public static void main(String[] args) {  
  11.         JavaMemoryPuzzle jmp = new JavaMemoryPuzzle();  
  12.         jmp.f();  
  13.     }  

在这个例子中,方法f()里定义了两个局部变量,变量data1和data2的作用域不同。按照正常理解,虽然两各个数组所需要的内存之和已经超过了可用内存,但是因为data1会被及时回收,不会出现内存溢出错误。

如果我们实际执行这个例子,会发现出现了java.lang.OutOfMemoryError错误。这是为什么?如果在BEA或者IBM的虚拟机上测试过这个例子,并不会出现错误。也就是说,SUN的JVM在内存回收机制上存在漏洞或者BUG。

这个问题该如何修正呢,方法其实很简单。只需要在变量作用域结束之前,将变量置为空就可以了。修改之后的结果如下:

  1. public class JavaMemory{  
  2.     private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);  
  3.     public void f(){  
  4.         {  
  5.             byte[] data1 = new byte[dataSize];  
  6.             data1 = null;  
  7.         }  
  8.         byte[] data2 = new byte[dataSize];  
  9.     }  
  10.  
  11.     public static void main(String[] args) {  
  12.         JavaMemoryPuzzle jmp = new JavaMemoryPuzzle();  
  13.         jmp.f();  
  14.     }  

发现这个问题,对于Java开发者来说也许会很紧张,担心自己的代码是否会出现同样问题。大家尽可放心,连续出现两个变量占用内存之和超过内存限制的情况概率非常小。并且在两个变量之间,如果定义了其他变量也不会出现这个问题。如下面的代码就不会出现问题:

  1. public class JavaMemory{  
  2.     private final int dataSize = (int) (Runtime.getRuntime().maxMemory() * 0.6);  
  3.     public void f(){  
  4.         {  
  5.             byte[] data1 = new byte[dataSize];  
  6.         }  
  7.     int i=1;  
  8.         byte[] data2 = new byte[dataSize];  
  9.     }  
  10.  
  11.     public static void main(String[] args) {  
  12.         JavaMemoryPuzzle jmp = new JavaMemoryPuzzle();  
  13.         jmp.f();  
  14.     }  

 

【编辑推荐】

  1. 专题:Java线程
  2. Java Swing多线程死锁问题解析
  3. 有趣的Java对象序列化缓存问题
  4. Java实用技巧:当不能抛出checked异常时
  5. Java编程语言的优点快递
责任编辑:佚名 来源: 51CTO
相关推荐

2019-11-20 15:02:45

Java虚拟机内存

2009-10-09 09:42:07

虚拟机内存

2020-03-10 09:30:11

Java内存数据

2019-04-09 15:56:46

虚拟机内存区Java

2009-06-18 13:51:07

Java虚拟机

2011-05-26 15:41:25

java虚拟机

2010-09-17 15:47:14

TOMCATJVM

2013-12-23 09:25:21

2018-03-28 14:58:42

虚拟机内核系统

2011-12-28 13:38:00

JavaJVM

2009-06-04 16:27:39

Java虚拟机JVMGC

2017-02-21 16:40:16

Android垃圾回收内存泄露

2012-08-14 10:05:08

2010-09-25 11:32:24

Java内存泄漏

2018-02-06 22:18:47

Java虚拟机面试

2009-06-17 15:46:36

Java运行时本机内存

2020-06-23 09:48:09

Python开发内存

2012-08-29 07:54:11

2013-04-09 14:49:18

Linux内存统计内存泄露

2021-04-14 18:58:01

虚拟机 Java内存
点赞
收藏

51CTO技术栈公众号