前言:为什么要研究JVM?
在实际生产环境中,内存是有限资源。JVM研究的主要是怎样使用内存,熟练掌握JVM,能利用有限的内存资源更加高效地运行程序。
JVM的结构
1.PC寄存器
2.JVM stacks
3.本地方法栈
本地方法接口
4.JVM方法区
5.堆区
6.GC
问题*
1.内存泄漏和内存溢出的区别?
内存泄漏:是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果
内存溢出:通俗理解就是内存不够,通常在运行大型软件或游戏时,软件或游戏所需要的内存远远超出了你主机内安装的内存所承受大小,就叫内存溢出。
一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光,导致内存溢出 。
2.常量池和运行时常量池的区别
常量池位于字节码文件,是静态的。
运行时常量池位于方法区,是动态的。
注意:从jdk7开始,运行时常量池中的StringTable被搬迁至堆中了。
3.JVM调优?
JVM调优的终极目标:保障程序的正常运行。
主要是通过对内存的调优来实现。
内存调优原则:尽量多给,尽量少用,尽量回收。
尽量多给:如从JDK8开始,方法区使用元空间取代永久代。元空间不设置在JVM内存中,而是使用本地内存,这样可以避免早期永久代时容易出现OOM的问题。虽然元空间不是位于JVM内部,但是此举相当于变相给JVM增加了内存。此外,还可以通过具体的设置,增加JVM内部其他模块的内存。
尽量少用:如在程序中通过allocateDirect使用直接内存(直接内存和元数据区一样,都位于本地内存中);在代码中避免出现内存泄漏;少用大对象。
尽量回收:如尽量及时通过垃圾收集技术将方法区和堆中内存空间收回;大对象用完及时close。但是,GC过多也会影响程序的运行,因为GC会导致STW,整个应用程序的线程都会被暂停,没有任何响应,严重影响客户体验。因此只能尽量使用GC,而不可以无节制地使用GC。
参考:
https://blog.youkuaiyun.com/weixin_42447959/article/details/81637909
https://blog.youkuaiyun.com/Javazhoumou/article/details/99298624
https://blog.youkuaiyun.com/weixin_34401008/article/details/113073208
写在最后
从本质上来讲,JVM虽是一个进程,实则是一个能调度线程级别的操作系统,JVM通过内部调度线程,来提高自身的运行效率。其内存主要分为两大部分:线程私有(PC寄存器、JVM stacks、本地方法栈)和线程共享(方法区、堆区)。
在学习JVM时,一方面要理清各个区域的作用,另一方面要理清在JVM运行时各个区域之间是如何配合的。