【狂神说JAVA】JVM快速入门-3

6、Native关键字

方法前带了native关键字的,说明java作用范围达不到了。回去调用底层C语言的库。

本地方法接口,用于ext拓展java功能。在内存区域专门开辟了一块标记区域,native method stack本地方法栈,登记native。会进入本地方法栈,调用本地方法的接口 JNI接口。JNI的作用:扩展Java的使用,融合不同的编程语言为java所用。最初是想融合c、c++。因为java诞生的时候,C、C++横行,想要立足必须要调用C,C++的程序。

native method stack本地方法栈,在本地方法栈中登记native方法,在execution engine执行引擎执行的时候加载native libraries本地库。

7、PC寄存器

就是6中图中的程序计数器。

8、方法区

即static,final,class,常量池就这四种上面标黄要背下来。

9、栈

先进后出

main函数先开始后结束。main先压入栈底,先执行,等所有其他函数 都执行完毕,在最后出栈。

10、3种JVM,sun公司的hotspot火锅是我们常用的。

11、堆

heap,一个jvm只有一个堆内存。堆内存的大小可以调节的。

类加载器读取了类文件后,一般会把什么放到堆中呢?类,方法,常量,变量,保存所有引用类型的真实对象。

堆内存中还要细分三个区域:

  • 新生区(伊甸园区)young/new

  • 养老区 old

  • 永久区 perm

其中,好多次没被垃圾回收GC-garbage collect掉,就进入幸存0,1;过一段时间,还没被回收掉就进入养老区。垃圾回收有轻量级的GC,还有当养老区都快满的时候,重量级的GC。

GC垃圾回收主要在伊甸园区和养老区。内存满了即OOM,out of memory堆内存不够,说明程序严重,堆都爆了。

JDK8以后,永久存储区就叫“元空间”了。

12、新生区

类:诞生和成长的地方,甚至死亡。

分为伊甸园区和幸存者区(0区和1区),所有的对象都是在伊甸园区new出来的。

假设伊甸园区大小是10个,等到伊甸园区满的时候,会触发轻量GC,删除了9个,幸存了1个进入幸存者0区。那么此时伊甸园区又有10个空位置了。

这里注意幸存者0区和幸存者1区是来回交换的,不是动态不变的。

等到幸存者0,1区都满了,触发重GC,留下来的存到养老区。

真理:经过研究,99%对象都在伊甸园区就结束了,很少看到OOM报错。(可以新建一个字符串,一直往上加字符,加到爆OOM)

13、永久区

这个时候就是微服务的好处了,每个服务不用加载那么多类。

伊甸园区的各个对象调用方法区的方法。上面这个图是存在于堆区的。而元空间和方法区其实不是存在于堆中的,所以又叫非堆。

其实从上面的架构图中,方法区和堆区是分开的。jdk1.8之前,方法区逻辑上在堆中,但是实际和堆内的其他区域隔离开。1.8之后,方法区只剩了概念,而元空间变成了留在堆中。

 

实验测试一下

默认情况下,最大将近2G,电脑8G,差不多1/4。而初始化内存120M,差不多是8G的1/64。

 

其中VM-option一栏,设置虚拟机的内存大小。-Xms和-Xmx表示初始内存和最大内存分别是1024M,-XX是将结果打印出来。结果

这里的from和to是幸存0区和幸存1区来回切换。并且注意到上图,新生区+养老区=981.5M刚好等于total的内存大小。所以元空间包含方法区包含常量池都是逻辑上存在,但是物理上不存在的。

再比如实验:

这里面:GC一直在清理内存,后来又有了重GC,再轻GC,再重GC。看代码注意到是前面讲的不断在字符串上加字符,堆内存总会撑爆。

14、堆内存调优

面试官问:遇到了OOM吗?遇到了,说明是堆内存满了。

措施:尝试扩大堆内存看结果;分析内存,看一下哪里出了问题,就是上面的print,或者使用下面专用的插件。

 

一个项目中,具体如何排除OOM故障:

  • 能够看到代码第几行出错:内存快照分析工具:MAT,Jprofiler

  • debug,一行行分析,不太现实。

MAT和Jprofiler的作用:

  • 分析dump内存文件,快速定位内存泄漏。

  • 获得堆中的数据

  • 获得大的对象

  • 。。自行百度

 

Jprofiler作为插件在idea的拓展plugin中安装,并且可以作为软件可以在电脑上安装客户端。使用举例:

抛出OOM异常,但还是看不出什么异常。所以需要在内存块中dump一些东西看,在配置中写入以下

此命令的意思是,出现OOM异常的时候将heap dump出来。

爆出这样的错误后,发现这个dumpfile已经生成,右键寻找sourcefile,找到当前代码所在文件夹下,cd../../,在code文件夹下就有相应的dumpfile文件,双击打开Jprofile文件。

再点击biggest object,看谁占用最大

点击左侧thread dump看线程,这里只有一条main线程

所以,下图中,想要知道其他错误,只需要改成其他错误名,写进配置中的VMoption就可以生成dump文件dump内存,定位错误了:HeapDumpOnXXX错误。

栈里面是没有垃圾的,只有堆里面有。

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页