研究一下Java的内存管理

 这里用一些简单的例子看一下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.<init>(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制空,致使下次循环重新赋值时才制空,因此内存回收会延后一次循环。
以上或有错误,请大家留言。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值