热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

研究一下Java的内存管理

这里用一些简单的例子看一下JVM的内存使用与管理方式。1.建立一简单程式,查看默认情况下JVM可使用的最大内存publicclassMemoryDemo{

 这里用一些简单的例子看一下JVM的内存使用与管理方式。

 

1.建立一简单程式,查看默认情况下JVM可使用的最大内存

public class MemoryDemo{
    public static void main(String[] args){
        System.out.println(Runtime.getRuntime().maxMemory());
    }
}
运行结果为66,650,112,也即约为64M

2.建立一个大的字符串数组,查看内存的使用情况

public class MemoryDemo{
    String[][] list = new String[100][100000];

    public static void main(String[] args){
        MemoryDemo demo = null;
        long memoryUsed = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
        demo = new MemoryDemo();
        System.out.println(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() - memoryUsed);
    }
}
运行结果:39,921,008,根据Java API中的资料,这个数据的单位为byte,我们分配的数组的大小为:100 * 100000 = 10,000,000,也即数组中的每个Item占用的空间大概为4 bytes。

3.简单修改代码,可引起OutOfMemoryError

public class MemoryDemo{
    String[][] list = new String[100][100000];

    public static void main(String[] args){
        MemoryDemo demo = null;
        int i = 0;
        while(i++ <10){
            System.out.println(i);            
            demo = new MemoryDemo();
        }
    }
}
可以看到,初始化第二个MemoryDemo对象时内存溢出。

4.修改代码,重写finalize方法,查看JVM内存回收情况

public class MemoryDemo{
    String[][] list = new String[100][100000];

    public static void main(String[] args){
        MemoryDemo demo = null;
        int i = 0;
        while(i++ <10){
            System.out.println(i);            
            demo = new MemoryDemo();
        }
    }

    protected void finalize(){
        System.out.println("System run gc");
    }
}
运行代码,当然仍时错误,说明JVM没有运行gc释放内存

5.修改代码,在循环内将demo指向null,并调用gc,以使JVM将第一次新建对象标记为可回收

public class MemoryDemo{
    String[][] list = new String[100][100000];

    public static void main(String[] args){
        MemoryDemo demo = null;
        int i = 0;
        while(i++ <10){
            System.out.println(i);            
            demo = new MemoryDemo();
            demo = null;
            System.gc();
        }
    }

    protected void finalize(){
        System.out.println("System run gc");
    }
}
再次运行,程式可正常运行,结果如下:1
2
System run gc
3
System run gc
4
System run gc
5
System run gc
6
System run gc
7
System run gc
8
System run gc
9
System run gc
因我们的最大内存为64M,而数组分配占用的内存为40M,所以如果不进行内存的回收,程式应该只能跑一次循环,这里JVM可以正常进行内存的回收。 

6.删除上例中的System.gc(),再次运行,

结果如下:1
2
System run gc
3
System run gc
4
System run gc
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at MemoryDemo.(MemoryDemo.java:2)
        at MemoryDemo.main(MemoryDemo.java:9)程式会在循环的某处发生OutOfMemoryError,可以看到JVM本身的内存回收似乎还有一点问题。

7.增大JVM内存,使其最大内存略大于数组所需内存的2倍,

即运行时使用 java -Xmx75m MemoryDemo,发现循环仍然会有中断情况,继续加大内存到略大于所需内存的3倍,即java Xmx121m MemoryDemo,可正常运行,未再发现有OutOfMemoryError,不知JVM是否需要分配至少三倍于所需内存才可正常运行,有待确认。

8.回到第5例,去除代码中的demo = null

public class MemoryDemo{
    String[][] list = new String[100][100000];

    public static void main(String[] args){
        MemoryDemo demo = null;
        int i = 0;
        while(i++ <10){
            System.out.println(i);            
            demo = new MemoryDemo();
            System.gc();
        }
    }

    protected void finalize(){
        System.out.println("System run gc");
    }
}
运行仍然会报OutOfMemoryError,增大内存至121m,代码可正常运行,分析原因为:由于没有使用demo = null语句及时将demo制空,致使下次循环重新赋值时才制空,因此内存回收会延后一次循环。
以上或有错误,请大家留言。

推荐阅读
author-avatar
当时桃花恨春风_375
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有