第二章的内容主要是JVM的内存管理。先不细看这部分内容,这里先写下对于一些问题的思考,以便更好地理解后续内容。
在刚开始接触Java的时候,也曾经看过JVM相关的内容。但是那个时候读到各种文章,一上来就会看到那张经典的JVM内部结构图。而在各种面试中,这些内容也是会被反复问到。当时只是觉得这个东西太重要了,要想在这条路走下去是必学的,但是里面的具体内容看得真是一头雾水。
现在,已经知道JVM之所以重要,是因为它解决了不同平台的资源适配(跨平台),简化了甚至弱化了开发人员在内存管理的很多麻烦,基本把Coder屏蔽在了外面。那么我们想象一下,如果是让我们来管理内存,会怎么去着手这个问题呢?我们来看一些,虽然简单,但对于我们理解JVM有帮助的一些常识。
JVM也是一个软件、也需要和其他软件共享计算机的内存。 我们所有Java运行中所处理的对象或者算法都使用JVM的内存空间 Java 也可以通过一些参数去控制JVM内存的使用量。如:最小内存 XMS、最大内存 XMx 按照正常理解,JVM用于创建对象,随着对象数量的增加,JVM使用率也在增加。如果JVM使用率达到100%就无法使用,为了让JVM可以让更多的对象重复使用,我们需要垃圾回收。 垃圾:不会被使用的对象。 所以JVM中的空间是被循环使用的 为了提高垃圾回收的效率,JVM将内存区域进行了划分
所以,要慢慢理解这个JVM的内部构造为什么会是这个样子,我们需要找到一种解释,就是它为了高效地解决问题,何以不得不成为现在的样子。
首先,JVM中是可以启动多个线程的,也就是说,这些线程有各自的私人领地,也会有很多公共资源供这些线程共同使用,这一点是很好理解的。所以为了屏蔽各个线程之间的影响,JVM把内存划分为了栈内存和堆内存。
栈内存就是给各个线程使用的,而堆内存是大家一起使用的公共领地。一个JVM中,我们可以启动多个线程,如果说线程的数量多了,那么栈内存所使用的的资源肯定会增多的,所以从这个角度上来说,也就比较好理解为什么栈内存的大小会比堆内存小很多了。在线程的执行过程中,我们知道如果是单核CPU,那么线程的执行肯定是轮流来执行,那么不同的线程执行到哪一句了,这个信息JVM肯定是必须要管理的,所以这就是线程中的程序计数器的作用。而在线程中(包含主线程)执行的方法,在这里被方法栈进行管理,具体如何管理可以细看书里的描述,另外JVM单独使用了本地方法栈来处理native定义的方法,这些方法是JVM通过JNI来调用其它语言所实现的方法,所以比较特殊,需要单独管理。这样一来,我们就梳理清楚了线程中的程序计数器,本地方法栈,方法栈三块内容。
堆内存中,主要关注的是,就这么一块区域,JVM是如何做到能让我们的代码不断地去new新的对象,保持程序长时间稳定运行的,它是怎么管理、归类这些对象,从而提高了内存使用的效率?对我们写代码又有哪些启发,更好地写出高效代码?有了这些疑问,对于新生代、老年代...概念也就有了些感性地理解,只需要知道这些概念以及所出现的管理逻辑都是JVM为了更高效地去管理堆内存出现的就好。
剩下还有比较重要的是方法区,里面还有常量池,为什么会这么设计,为什么要把类信息,各种常量等等都放入这个区域?把这些不可变的内容放入这个区域,是为了让线程、堆内存中所有的内容都保证为可变的,以便于在对象回收和线程资源回收时降低处理的复杂度吗?
另外,这几个区域就是JVM的全部吗?
带着这些问题,和自己想到的可能的解释,再次进入深入理解JVM,我觉得应该能够收获的更多。这一篇内容是我在查阅了一些资料基础上,进行了一些猜测,主要目的就是要在进入JVM细节之前,自己在脑海中构建一套与JVM大体结构相同的框架下,试图去理解设计者的意图。在此基础上,再次查看相关内容,我觉得更能够抓住重点,有的放矢。希望也能对看到这篇文章的初学者有所帮助。
【参考】
https://www.cnblogs.com/sunweiye/p/10852540.html