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错误。
栈里面是没有垃圾的,只有堆里面有。