jvm狂神视频笔记---native和垃圾回收器

native关键字
凡是带了native关键字的,说明java的范围达不到了,会去掉底层C语言的库~
会进入本地方法栈,调用本地方法本地接口 JNI(java native Interfance)
JNI 的作用:扩展Java的使用,融合不同的语言为Java所用
他在内存域中专门开辟了一块标记区域:NativeMethodStack, 登记native方法
在最终执行的时候加载本地方法库中的方法通过JNI

native用法:
1.编写带有native声明的方法的Java类(java文件)
2.使用javac命令编译编写的Java类(class文件)
3.使用javah -jni ****来生成后缀名为.h的头文件(.h的文件)
4.使用其他语言(C、C++)实现本地方法
5.将本地方法编写的文件生成动态链接库(dll文件)

PC寄存器

程序计数器: Program Counter Register

每一个线程都有一个程序计数器,是线程私有的,就是一个指针,只向方法区的方法字节码(用来存储指向像一条指令的地址,也即将要执行的代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。由于JAVA虚拟机的多线程是通过线程轮转切换并分配处理器执行时间的时间来实现 ,在任何一个确定的时间(对于多核处理器来说是一个单核)都会执行一条线程中的指令。因此,为了线程执行后能恢复到正确的位置,每个线程都需要有一个独立的程序计数器,各条线程之间计数器相互不影响,独立存储,称这类内存区域为“线程私有”的内存。

方法区 Method Area

方法区是被所有线程共享,所有字段和方法字节码,以及一些特殊方法,如构造函数,接口代码也在此定义,简单说,所有定义的方法都保存在该区域,此区域属于共享区间

静态变量、常量、类信息(构造方法,接口定义),运行时的常量池在方法区中,但是实例变量存在堆内存中,和方法区无关

堆区:提供所有类实例和数组对象存储区域

jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身

栈区:每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。

思考:Java中的对象是在堆上创建的,对象的引用是放在栈里的?
了解Java逃逸分析和及时编译

方法区:又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。运行时常量池都分配在 Java 虚拟机的方法区之中

栈:栈内存,主管程序的运行,生命周期和线程同步;线程结束,占内存也就释放,对于栈来说,不存在垃圾回收问题栈: 8大基本类型+对象引用+实例的方法

在这里插入图片描述

垃圾回收

强引用:发生 gc 的时候不会被回收。
软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。
弱引用:有用但不是必须的对象,在下一次GC时会被回收。
虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。
GC垃圾回收,主要是在年轻区和养老区!
堆内存满了,会报OOM的错误~
在JDK8以后,永久存储区改名为元空间

堆的内存结构如下:
年轻代中 默认伊甸区:幸存区=8:1
在这里插入图片描述
有些人说堆只有年轻代和老年代,也对,毕竟元空间叫做非堆,但是元空间逻辑上的确存在
默认情况下:分配的总内存是电脑内存的1/4,初始化内存是电脑内存的1/64

        //返回虚拟机的最大内存
        long max = Runtime.getRuntime().maxMemory();
        //返回jvm的总内存
        long total = Runtime.getRuntime().totalMemory();
        System.out.println("max:"+max/(double)1024/1024+"M");
        System.out.println("total:"+total/(double)1024/1024+"M");

结果如图
在这里插入图片描述
如果哪里报OOM的错误就尝试扩大内存看结果,分析内存。
查看堆内存分配
在这里插入图片描述
在这里插入图片描述
年轻代+老年代就已经等于total
所以 元空间逻辑上存在,物理上不存在

在这里插入图片描述

Dump文件分析

-Xms 设置初始化内存分配大小 1/64
-Xmx 设置最大分配内存 1/4
-XX:+PrintGCDetails 打印GC垃圾回收信息
-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

使用JProfile查看分析内存

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述JVM在进行GC时,并不是对这三个区域统一回收。大部分时候,回收都是新生代~~

  • 新生代
  • 幸存区
  • 老年区
    -GC两种类:轻GC(普通的GC),重GC(全局GC)

GC题目:
JVM的内存模型和分区 ,详细到每个区放什么?
堆里面的分区有哪些?Eden, from,to 老年区,说说他们的特点!
GC的算法有哪些?标记清除,标记压缩,复制算法,引用计数器,怎么用的?
轻GC和重GC分别在什么时候发生?

复制算法最佳使用场景:对象存活度较低的时候;新生区;
好处:没有内存碎片
坏处:浪费了内存空间~;多了一半永远是空 to .浪费空间针对的就是对象100%存活(极端情况)

标记清除:
在这里插入图片描述

标记压缩:
在这里插入图片描述

标记清楚压缩

总结

内存整齐度: 复制算法 = 标记压缩算法 > 标记清除算法
内存利用率:标记压缩算法 = 标记清楚算法 > 复制算法

没有最好的算法,只有最合适的算法
GC:分代收集算法

年轻代,存活率低,适合使用复制算法
老年代,存活率高,当内存碎片不是太多时,使用标记清除,内存碎片变多时,使用碎片压缩。总的来说老年代是标记清除+标记压缩

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值