热门标签 | 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制空,致使下次循环重新赋值时才制空,因此内存回收会延后一次循环。
以上或有错误,请大家留言。

推荐阅读
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
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社区 版权所有