java的内存分配和垃圾回收

2020-08-10  本文已影响0人  积跬步以致千里_ylc

学习垃圾回收机制的意义

java和C++等语言的最大技术区别:自动化的垃圾回收机制(GC: Garbage Collection)
为什么要了解GC和内存分配策略:

通个一个实例来进行垃圾回收的分析

 public static void main(String[] args) {
        List<Object> list = new LinkedList<>();
        int i = 0 ;
        while (true){
            i++;
            list.add(new User());
            if(i % 10000 == 0) System.out.println("第"+i+"次");
        }
    }

    static class User{
        String name = "name";
        int age = 26;
        String sex = "女";
        String description = "is a kindness girl";
    }

堆的进一步划分

堆中空间的大小设置和分配命令--VM参数

GC如何判断对象的存活

各种引用

 static class Student {
        int id;
        String name;

        public Student(int id, String name) {
            this.id = id;
            this.name = name;
        }

        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }

    public static void main(String[] args) {
        //new 是强应用
        Student student = new Student(20200810, "学霸A");
        //创建一个Student的软应用
        SoftReference<Student> softStu = new SoftReference<>(student);
        //干掉Student的强引用只留下 软引用
        student = null;
        System.out.println(softStu.get());
        //进行一次垃圾回收,为什么不能手动的回收软引用,因为这个软引用在虚拟机栈的本地变量表中
        System.gc();
        System.out.println("GC 回收后:");
        System.out.println(softStu.get());
        //向堆中无限制的添加数据 制造OOM
        List<byte[]> list = new LinkedList<>();
        try {
            while (true) {
                //每一次循环就向list中添加1M的数据
                System.out.println("------------>" + softStu.get());
                list.add(new byte[1024 * 1024 * 1]);
            }
        } catch (Throwable e) {
            //抛出OOM异常时 查看软引用是否被回收
            System.out.println("报OOM异常时 软引用的值:" + softStu.get());
            // 为什么这个案例中,要oom的时候已经回收了软引用还是回爆出OOM异常
           //因为 while 循环还在不停的向list中添加对象 还在继续分配堆的内存,只是回收一个软引用
           //堆的内存仍然不够用的。
        }
    }

运行结果:

软引用在内存不够用的使用回收测试
软引用使用的场景:假如需要一个程序用来处理用户提供的图片。如果将所有图片读入内存,这样虽然可以很快的打开图片,但内存空间使用巨大,一些使用较少的图片浪费内存空间,需要手动从内存中移除。如果每次打开图片都从磁盘文件中读取到内存再显示出来,虽然内存占用较少,但一些经常使用的图片每次打开都要访问磁盘,代价巨大。这个时候就可以用软引用构建缓存。

垃圾回收的算法

堆内存分配策略

在JVM中实际使用分代收集(各种算法组合)

分代收集示意图
新生代和老年代的回收算法解析

Stop The World现象

在垃圾回收过程中经常涉及到对对象的挪动(比如上文提到的对象在from和to之间的复制),进而导致需要对对象引用进行更新。为了保证引用更新的正确性,Java将暂停所有其他的线程,这种情况被称为“Stop-The-World”,导致系统全局停顿。Stop-The-World对系统性能存在影响,因此垃圾回收的一个原则是尽量减少“Stop-The-World”的时间,GC收集器和我们GC调优的目标就是尽可能的减少STW的时间和次数。


红色的GC线程,绿色是业务线程
尽量减小GC暂停线程的时间

内存泄漏和内存溢出辨析

上一篇下一篇

猜你喜欢

热点阅读