栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > C/C++/C#

黑马jvm课程笔记d2

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

黑马jvm课程笔记d2

目录

一、直接内存相关

1.1.定义

1.2 ByteBuffer 作用

1.3文件读写过程

1.3 直接内存溢出和释放

二、垃圾回收相关

2.1 判断是否可以回收

2.2 五种引用​编辑

2.2.1 软引用应用

 2.2.2 弱引用应用

2.2 垃圾回收算法


b站黑马jvm课程学习笔记,第二篇

一、直接内存相关

1.1.定义

1.2 ByteBuffer 作用

使用直接内存ByteBuffer 读写大文件效率更高

public class Demo1_9 {
    static final String FROM = "目标文件路径";
    static final String TO = "存储路径";
    static final int _1Mb = 1024 * 1024;

    public static void main(String[] args) {
        io(); // io 用时:1535.586957 1766.963399 1359.240226
        directBuffer(); // directBuffer 用时:479.295165 702.291454 562.56592
    }

    private static void directBuffer() {
        long start = System.nanoTime();
        try (FileChannel from = new FileInputStream(FROM).getChannel();
             FileChannel to = new FileOutputStream(TO).getChannel();
        ) {
            ByteBuffer bb = ByteBuffer.allocateDirect(_1Mb);
            while (true) {
                int len = from.read(bb);
                if (len == -1) {
                    break;
                }
                bb.flip();
                to.write(bb);
                bb.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        System.out.println("directBuffer 用时:" + (end - start) / 1000_000.0);
    }

    private static void io() {
        long start = System.nanoTime();
        try (FileInputStream from = new FileInputStream(FROM);
             FileOutputStream to = new FileOutputStream(TO);
        ) {
            byte[] buf = new byte[_1Mb];
            while (true) {
                int len = from.read(buf);
                if (len == -1) {
                    break;
                }
                to.write(buf, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        System.out.println("io 用时:" + (end - start) / 1000_000.0);
    }
}

1.3文件读写过程

不使用直接内存,此时java缓存区和系统缓存区内得同时存储数据,降低速度

 使用直接内存:

1.3 直接内存溢出和释放

内存溢出模拟:

内存释放:

 直接内存的释放并非由垃圾回收System.gc()释放,而是由unsafe对象的freeMemory()方法来释放

直接内存的分配和回收原理:

二、垃圾回收相关

2.1 判断是否可以回收

(1)引用计数法

有可能出现两个对象互相引用的情况

(2)可达性分析算法

当对象没有直接或间接被根对象引用时,就可以被当做是垃圾回收

2.2 五种引用

五种引用简单关系图如下:

(1)实线为强引用

(2)当A2和A3没有B对象被强引用时,内存不足时软引用的A2会被回收释放;弱引用的A3一定会被回收释放

(3)当A2和A3被回收后,软引用对象和若引用对象会进入引用队列:

(4)虚引用和终结器引用一定要配合引用队列使用

当ByteBuffer被回收后,虚引用对象进入对列,并且执行Unsafe.freeMemory方法来释放直接内存

(5)终结器引用对象先进入队列,再释放A4对象

2.2.1 软引用应用
public class Demo2_3 {

    private static final int _4MB = 4 * 1024 * 1024;



    public static void main(String[] args) throws IOException {
        
        soft();


    }

    public static void soft() {
        // list --> SoftReference --> byte[]

        List> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            SoftReference ref = new SoftReference<>(new byte[_4MB]);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());

        }
        System.out.println("循环结束:" + list.size());
        for (SoftReference ref : list) {
            System.out.println(ref.get());
        }
    }
}

 软引用垃圾回收:

软引用——应用队列

public class Demo2_4 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        List> list = new ArrayList<>();

        // 引用队列
        ReferenceQueue queue = new ReferenceQueue<>();

        for (int i = 0; i < 5; i++) {
            // 关联了引用队列, 当软引用所关联的 byte[]被回收时,软引用自己会加入到 queue 中去
            SoftReference ref = new SoftReference<>(new byte[_4MB], queue);
            System.out.println(ref.get());
            list.add(ref);
            System.out.println(list.size());
        }

        // 从队列中获取无用的 软引用对象,并移除
        Reference poll = queue.poll();
        while( poll != null) {
            list.remove(poll);
            poll = queue.poll();
        }

        System.out.println("===========================");
        for (SoftReference reference : list) {
            System.out.println(reference.get());
        }

    }
}

 2.2.2 弱引用应用
public class Demo2_5 {
    private static final int _4MB = 4 * 1024 * 1024;

    public static void main(String[] args) {
        //  list --> WeakReference --> byte[]
        List> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            WeakReference ref = new WeakReference<>(new byte[_4MB]);
            list.add(ref);
            for (WeakReference w : list) {
                System.out.print(w.get()+" ");
            }
            System.out.println();

        }
        System.out.println("循环结束:" + list.size());
    }
}

2.3 垃圾回收算法

(1)标记清除算法

优点:速度快

缺点:清除未被引用的内存后,不会对整体内存空间整理,使得内存不连续,碎片化

(2)标记整理算法

优点:没有内存碎片

缺点:整理时,引用对象地址需要变化,花费时间增加

 

(3)复制算法

优点:不会产生碎片化内存

缺点:需要使用双倍内存

2.4 分代垃圾回收

新生代垃圾清理更频繁

老年代当内存不足时才会清理

2.4.1 虚拟机相关参数

GC分析

public class Demo2_1 {
    private static final int _512KB = 512 * 1024;
    private static final int _1MB = 1024 * 1024;
    private static final int _6MB = 6 * 1024 * 1024;
    private static final int _7MB = 7 * 1024 * 1024;
    private static final int _8MB = 8 * 1024 * 1024;

    // -Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc -XX:-ScavengeBeforeFullGC
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            ArrayList list = new ArrayList<>();
            list.add(new byte[_8MB]);
            list.add(new byte[_8MB]);
        }).start();

        System.out.println("sleep....");
        Thread.sleep(1000L);
    }
}

 运行输出:

sleep....
[GC (Allocation Failure) [DefNew: 4196K->894K(9216K), 0.0032025 secs][Tenured: 8192K->9084K(10240K), 0.0047001 secs] 12388K->9084K(19456K), [Metaspace: 4211K->4211K(1056768K)], 0.0081122 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[Full GC (Allocation Failure) [Tenured: 9084K->9028K(10240K), 0.0024288 secs] 9084K->9028K(19456K), [Metaspace: 4211K->4211K(1056768K)], 0.0024576 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
Exception in thread "Thread-0" java.lang.OutOfMemoryError: Java heap space
	at com.whx.cn.itcast.jvm.t2.Demo2_1.lambda$main$0(Demo2_1.java:20)
	at com.whx.cn.itcast.jvm.t2.Demo2_1$$Lambda$1/1023892928.run(Unknown Source)
	at java.lang.Thread.run(Thread.java:748)
Heap
 def new generation   total 9216K, used 1293K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
  eden space 8192K,  15% used [0x00000000fec00000, 0x00000000fed43528, 0x00000000ff400000)
  from space 1024K,   0% used [0x00000000ff500000, 0x00000000ff500000, 0x00000000ff600000)
  to   space 1024K,   0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
 tenured generation   total 10240K, used 9028K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
   the space 10240K,  88% used [0x00000000ff600000, 0x00000000ffed10b8, 0x00000000ffed1200, 0x0000000100000000)
 Metaspace       used 4747K, capacity 4900K, committed 4992K, reserved 1056768K
  class space    used 529K, capacity 592K, committed 640K, reserved 1048576K

Process finished with exit code 0

 

 

2.5 垃圾回收器

(1)串行

(2)吞吐量优先

 

(3)响应时间优先

 

  2.6 G1垃圾回收器 2.6.1垃圾回收阶段

 (1)新生代内存布局Young Collection

  (2)新生代回收+CM(Young Collection+CM)

(3)混合回收 Mixed Collection

 (4)Full GC

 

 (5)新生代跨代引用

 

(6)Remark

        重新标记阶段

        在垃圾回收时,收集器处理对象的过程中

        黑色:已被处理,需要保留的 灰色:正在处理中的 白色:还未处理的

(7)JDK 8u20字符串去重

 (8)JDK 8u40类卸载

 

 (9)JDK 8u60回收巨型对象

  (10)JDK 9动态调整阈值

 

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1037834.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号