前面一小节我们介绍了介绍了GC的一般性原理和垃圾回收算法,通过对前面知识的学习,我们基本掌握了垃圾收集的一般理论知识。但是理论终究知识在之上,距离真正的实践还有一定的差距。前面我们提到了第一个带有内存动态分配和垃圾收集的编程语言并不是 Java 而是1960年诞生的Lisp。当然这一小节中我们并不会梳理 Lisp 实现的垃圾收集器。这一小节我们会先从经典垃圾收集器入手,梳理各个垃圾收集器的特性、优缺点和适用场景。当然随着垃圾收集器的效率的不断提升其实现的复杂度也在不断提升。我们会主要的篇幅去介绍CMS和G1原理及部分实现细节,升华对垃圾收集器的理解。今天是六一儿童节,各位朋友坐好来,我们的梳理开始了。
我们都知道 Java 程序员不用像 C++ 程序员一样手动申请和释放对象空间,这是因为 JVM 垃圾回收器的存在。为什么需要垃圾回收呢?因为空间是有限的,而我们运行程序完成各种各样的计算需要申请空间。但是空间不是无限的,如果我们的空间不够申请怎么办?这个时候就要释放内存,删除掉一些不用的无效的空间,来腾出空间来创建我们需要的对象。这就像我们的衣柜一样,我们买衣服回来放在衣柜里面,但是衣柜不是无限大的,所以当衣柜放不下的时候,我们就要清理丢掉小了的或者我们不穿的衣服,这样为新的衣服腾出空间。Java 自带GC会自动清理内存空间,而C++这种没有GC的语言,就需要使用手动清理空间了。全自动不用程序员操心的确很好,如果放仍不管也会引起其他的问题,那么怎么清理起来才是正确且高效。这就是一个有意思的问题,这一小节我们将从 GC 的一般原理和垃圾回收算法开始,逐步展开 Java GC 的世界。
在前面的小节中,总结梳理了 JVM 底层的一些基础的东西,包括 JVM 字节码技术,方法的调用,反射,异常等方法流程,基础的最后一部分梳理了类加载机制和对象的内存布局。有了这一套机制 JVM 能够顺利的读取Java文件,并行执行逻辑。看起来都有了,但是少了一个重要的部分没错,就是内存。这计算机的内存这个部分来的像理所当然一样。其实最原始的计算机是没有内存这个概念的,后来冯诺依曼提出了冯诺依曼结构,冯诺依曼确定了计算机的结构,即确定了计算机的 5 大部件,即运算器、控制器、存储器、输入设备和输出设备。现代计算机的都是遵循冯诺依曼结构的,因此又称为冯诺依曼机。所以作为虚拟机怎么能没有内存呢?Java 内存模型规定了 JVM 应该如何使用计算机内存(RAM)。广义上来讲,Java内存模型分别为两个部分 JVM内存结构 和 JMM与线程规范。
在前面一篇中提到了方法的调用,方法在类加载阶段会由符号引用替换实际引用或者方法表的索引。Java 的类加载机制又是怎么样的呢?我记得我刚毕业那会去面,基础的问题都回答的挺好的但是最后面试官问了我这个问题,Java 虚拟机是怎么加载一个类的?我当时脑子懵了,对象怎么加载到内存?对象是 new 出来的的啊,还要加载?我也对这块不太了解,然后面试官也就没深了问。但是现在看来,如果是进阶 Java 的话这是一个基础不能在基础的问题了。类加载了这还不算完,Java 的类是怎么保存的,我相信很多朋友会回答存放在堆里,那其他特殊的类型呢 例如 String 类型又是怎么存储的呢?我们在内存溢出的时候,对象怎么就把我们的堆给堆满了,每个对象占了多大的空间呢?请朋友们慢慢往下看。












