00:00
下面呢,咱们就进入咱这一章的这个主角,叫做这个堆,OK啊,那这一章的话呢,也是我们整个讲这个运营时,数据区中最重要的啊,叫最重要其实不为过啊,最重要的这样一个章节堆,我们从这样的几个方面呢来进行讲节,首先的话呢,我们对这个堆的一个核心概述啊,涉及到关于堆的一些呃,最基本的一个描述,这里边儿的每一个描述呢,大家都要收集于心啊,都要非常清楚,这呢也构成我们整个要讲解这个堆的一个初始的一个架构啊。那其次的话呢,我们去设置一下堆内存的一个大小,这个堆的话呢,我们说是可以咱们通过相关的这个GM参数呢,来进行内存大小的一个设置的,这个是没有问题的,那如果说我们在真正使用当中,超出了咱们设置堆内存的这个最大的空间的话呢,就会报一个叫OM啊叫hi space是吧?啊就是堆空间的一个内存溢出,那么我们这儿呢,也给大家举一个相关的这个例子。哎,那咱们真正的在开发当中呢,肯定是要尽量的避免这个OM出现的,对吧?OK,然后下一个的话呢,我们又提到一个叫年轻代与老年代啊,这呢是什么概念呢?就堆空间啊,是咱们整个这个运行时数据区啊,咱们还是打开这个简图啊,就是光空想的不行,咱们就还是看着图来说,这呢是咱们整个这个运行时数据区在这个区间当中啊,我们说这个堆空间啊,差不多呢,是咱们所要建到的一个最大空间了。
01:21
啊,当然这个方法区的空间呢,其实也不小哈,这个堆空间的话呢,差不多是我们所要考虑的这些内存当中的一个最大的空间了,那么这个空间的话呢,我们为了更方便的进行对象的一个分配,诶,我们又把它划分成划分出呢叫年轻贷和老年贷。啊,或者有的也叫做这个新生代啊,新生区啊,与这个养老区啊,这个等等相关的一些这个名字啊不太一样,当然这个意思是一样子的,我们这儿呢,就称为叫年轻代与老年贷了,那么年轻领导老金贷呢,这个我们看一下这个对象呢,到底放在哪儿,是先放到年金贷,什么时候呢放到老年贷,这个到这个块呢,我们会具体的给大家来讲解,包括在这个年轻贷呢,我们还可以对它呢再进行细分,除这个叫伊甸园区和这个survivor啊,就是幸存者零区一区,OK,这个我们到这儿呢,再具体来说,然后再往下的话呢,提到一个叫对象的一个分配过程。
02:10
哎,我们说堆空间呢,主要是用来是不是来这个存放咱们的这个对象是吧,还有我们这个数组对象。啊速度结构,那么针对于这个对象的话呢,我们是如何进行一个分配的,这呢,我们通过这个图解的方式呢,给大家说清楚,这呢也是一个比较基本的一个内容啊,就大家呢知道学这个堆,那个堆最基本的就是存对象,那个对象的这个在堆中的一个变化过程是什么样子的,这个呢大家一定要清楚。那接下来的话呢,我们再谈一谈,这叫me j c me j c和for g c,那这儿呢,主要涉及到咱们这个对象呢,在分配的过程当中,它在这个内存的细节当中啊,年轻贷又放到这个伊甸园区,什么时候又跑到新存者零区,什么时候又跑到老年贷,在这个过程当中,不可避免的会出现这个叫垃圾回收。哎,就是我们所谓的这叫JC是吧,那么这个垃圾回收啊,咱们在这块呢,其实就会涉及到啊,后续呢,咱们讲到这个后边这个章节的时候,咱们讲到这个像十三十四十五十六是吧,哎,这些章节的时候呢,咱们还要讲这个JC。
03:11
诶,那到那个时候呢,我们还要说他再提到这里边儿的几种这个情况,因为呢,这个不同的垃圾回收,在不同的垃圾回收算,呃垃圾回收器当中,它这个实施的方案啊,有些不一样,所以到那个时候呢,我们还会再谈一谈,包括呢,我们后边讲这个性能提升的时候是吧,性能优化的时候呢,咱们也还要再去说这个垃圾回收。啊,只不过呢,现在呢,咱们谈的呢,就是基于咱们目前的需要,咱们谈这里边儿的一些点啊。好,再往下的话呢,提到这个堆空间的一个分带思想啊,为什么我们要进行分带啊,就是为了更好的进行一个对象的存储,包括这个对象呢,本身这个特点也不一样是吧?哎,我们进行了一个分带思想啊,到这呢,具体说下面呢,叫内存分配的一个策略啊,提到这个年轻代老年代,那以及呢,在一些特殊情况下呢,我们该如何进行一个对象的分配啊,这呢就提到一个分配策略啊,这呢需要大家清楚。然后再往下呢,我们提到说为对象呢,去分配内存,提交到一个叫t lab。
04:05
嗯,TRB,咱们说到这儿的时候呢,咱们具体来讲啊,主要呢,原因是因为咱们对空间呢是共享的。啊,一个进程中的多个线程是不是共享的呀?哎,那既然是共享的话呢,这块说我们为了更好的提高这一个线程操作的一个呃,效率并发性是吧,我们给每一个线程呢,在独立的分配了一个叫TLED哈,然后在下边呢,我们总结一下堆空间中的这个参数设置。啊,参数设置就是整个咱们在上述的讲验过程当中啊,有很多这个参数呢,需要进行设置,那我们这块呢,我们做一个小结,哎,在这个大场面试题当中啊,关于这个,呃,国内的这些大厂,比如说这个蚂蚁金服啊,嗯,腾讯呐,百度啊,这个滴滴呀,美团呀,是吧?呃,包括这个拼多多,抖音等等啊,那相应的这几个大厂的话呢,这两年的面试题呢,我都看了,基本上呢,其实一总结也就那一些,其中有一部分呢,就是来问一问这个我们在整个GM使用过程当中呢,你常用的这个设置参数都有哪些?
05:01
那么这个参数里边呢,我们在堆空间这块呢,涉及到了有一波,哎,这一波呢,需要大家看一看,练一练啊,背一背是吧?哎,得清楚啊,因为你调约的时候呢,肯定是不是也要设置这些参数啊。对吧,还是这个问题啊好,然后最后呢,我这用了一个罗马数字十啊,要不写俩一零的话,那就乘不像啊罗马数字十说呢,堆是分配对象的唯一选择吗。啊,同学呢,一问到这个问题就蒙了,哎,对分配对象没问题啊,是唯一选择吗?啊这个如果你要是不知道这个知识点的话呢,你根本也不敢蒙对吧?啊,因为你要是蒙完以后呢,人家可能问说你是怎么理解的啊,下边就没法谈了。哎,这里边我们要强调的是呢,就堆呢,并不是我们分配对象的唯一选择,那么还有哪些结构呢?哎,咱们讲到这是什么再说。好,这呢,就是整个我们要讲解的这十个问题是吧,那那下边呢,就咱们具体展开呢,来说明这个一个核心概述啊,那首先的话呢,我们看到咱们这儿呢,讲解的是这个堆空间啊,堆空间呢处在我们整个。哎,整个呢,咱们这个剪图当中的这个上层中层下层当中的这个中层这块的这个对空间。
06:06
哎,在这个位置上对吧?行,那么这个堆空间呢,大家也明显看到我们这里边换个颜色啊,这个方法区跟堆呢,我是不是用的红色来表示啊,哎,一方面呢,是说明它俩呢比较重要啊,其次的话呢,想说明的问题就是这两个空间啊,这两个结构呢都是什么呀?哎,对一个进程来说。嗯,对一个进程来说呢,他们各自是唯一的,哎,大家还记不记得咱们之前说过这个问题哈,说呢,咱们一个Java程序的运行起来以后呢,咱们说是不是有一个进程。没问题是吧,那么这一个进程咱们就对应着一个叫GVM的一个实例。你要记住它啊。一个进程呢,咱们就对应着一个GM的实例,一个GM实例当中咱们就有一个运行时数据区,就是咱们所谓的叫runtime啊,咱们的runtime是不是还设置成是个单例的了,Java中是不是有这样一个类啊啊,一个二函式的一个设置方式啊,那么这个runtime里边的话呢,它就有独立的,只有一个堆,只有一个方法区。
07:06
啊,这是一个实例,那一个实例呢,是不是就对应了一个进程,那一个进程当中,咱们说是不是有多个线程吧。多个线程,那就意味着咱们一个进程当中的多个线程是不是要共享同一个对空间啊,共享同一个方法区吧。哎,没问题是吧,哎,是这样的,那么每一个线程呢,咱们说他们各自呢,拥有一套各自啊拥有一套乘序计数器,本地方法站虚拟站是吧?啊每个线程一份,哎,所以这呢,用灰色的来表示啊,就是各个线程啊,一个线程一份啊这俩呢大家共享。哎,共享啊,一想到共享这个问题,是不是我们就要考虑到现场的一个安全问题啊,哎,这个这个大家的直观的反应是对的啊。嗯,行,这呢,就是我们说的这个运营式数据区,大家先明确一下这个概念啊,咱们现在要讲的是这个堆啊,他讲的是这个结构。
08:00
好回过来,那么关于这个结构呢,咱们看一看啊,它这块呢,有这样的一些说明,这呢就是咱们逐条呢给大家去讲解的,这呢也是我们对堆的一个认识的最初的这样的一些印象,哎,构成我们整个关于堆的一个呃,初始的一个基础架构啊,首先呢,这块提到说一个GM实例呢,只存在着一个堆,内存堆呢,也是咱们Java内存管理的一个核心区域,刚才是不是已经说到这个问题了。啊好,下一个啊说Java堆取在GM启动的时候呢,就被创建了啊应该这样说,咱们GM什么时候启动啊,是不,你把这个程序运营起来的时候,我们GM实例诶,就通过一个叫bootrap啊,叫阴道类加载器呢,就帮我们把它启动起来了,GM1启动咱们这个堆区,GM1启动呢,你相应的这个呃,运行是数据区这个是不是就创建了,它一创建的话呢,我们相应的这个堆呢,是不是也有创建了,那堆一创建呢,它的这个空间呢,也就确定了。哎,这只是一个连锁的一个对应关系。啊堆只要你一提供好,咱们这个大小呢,也就确定了,哎,有点像咱们说那个数组一样是吧?哎,数组一旦扭好,是不是空间就确定了。
09:06
哎,不会说这个堆呢是可大可小等等,不会的啊,这里边也提到说这个GM呢,呃,这个堆呢,也是咱们这个GM当中要管理的最大的一块内存空间了。在要管理的最大的一块内存空间,同时呢,我要把它说是最重要的一块内存空间,其实呢,也不为过。啊,其实也不为过啊,这个对呢,一会儿咱们也要提,它是咱们这个垃圾回收也是一个重点的区域,也是咱们要想竞争性调优的一个重点的一个区域啊,所以它最重要最核心啊,都不为过行,然后呢,下边提到说这个堆内存的大小呢,是可以调节的。啊,它也必须得可以调节是吧,你像我们这个程序呢,如果比较大的话呢,咱们是不是就可以分配的这个内存空间要大一些,尽量的降低是不是这个JC啊,这这个这个这个叫频度是吧?啊频率啊,那同时的话呢,你这个堆内存要如果小的话呢,是不是你再垃圾回收它可能有些问题也搞不定包OM了,是不是就更不好了,所以呢,我们是可以调节大小的啊,要注意。
10:03
好,下一个说呢,这个呃,虚拟机规定啊,这个咱们先别看,先把这个上面这个提到了,说一个实例就对应的一个堆内存,咱们给大家演示一下啊,我这儿呢,提前把这个idea呢,已经启动好了,针对于咱们这个第八章打开程序。诶,这里边呢,我写了一些代码啊,咱们主要呢先看这两块,一个呢叫黑DEMO,一个叫黑代一,嗯,这里边儿的代码是一样子的,非常简单,所以这呢我就没有自己提前写了,咱们就写好了啊来分析开始结束,中间呢有让我们当前这个程序再去停顿,这个叫1000秒。按1000秒去算的时间还挺长的啊行,这呢是我们说的这个程序,然后第二个程序呢,跟大家完全一样。好,然后的话呢,我们在这两个程序呢,运营起来之后呢,对应的是不是就两个进程啊,那两个进程我们看一下他们是不是各自有各自的这个堆,那你怎么证明啊,那咱们是不是给它们分配不同的这个堆空间就可以了。哎,咱们看一下这个数据是不是就一目了然行,那么我们去添加这个参数的话呢,就是我提前已经写好了,这个参数呢,是我们在这个运行环节加进来的,也就当我们去执行这个Java指令的时候。
11:05
哎,咱们之前呢,是不是,呃先得编译是吧,编译的话呢,是不是叫Java c啊,编译完以后生成的自源码文件,当我们执行这个Java指令的时候呢,把这两个参数呢,给它加进去。哎,是这个意思啊,那编译编译咱们也用不着提前说我先跑一下是吧,然后再重新再过来加参数啊,没必要了,咱们直接呢,在这个build这块啊,注意先选中我们这个第一个程序啊,Build这块呢,我们做一个re compel啊编译。是吧,看这不我们编译的是这个啊,然后呢,找到我们第二个程序,把它呢也做一个编译。行都编译了,都编译完以后呢,回到我们这个run在这个位置呢,我们找一下这个I conguations打开啊,诶左边呢,这块又显示出来,如果呢,大家这块没显示的话,你在这块。这块有点节点是吧,第二点这块呢,去搜啊叫he一个DEMO。是吧,在DEMO就能搜到啊,那如果有同学你搜不到的话,你看一看你这块,那这个注意咱们现在是不是在第八章啊,那这个你记着选的是第八章啊,选别的章呢,你去搜肯定也搜不着,第八章当中我们先针对是咱们这叫hi DEMO啊,针对它在这儿呢,填我们这个参数。
12:09
哎,这个大XMS10兆,这呢是咱们这个堆的一个初始的大小啊,一会儿呢,咱们还会专门再说啊,大XMX这我也设置成十兆,就是这个初始的一个对空间和最大的对空间呢,都是十兆行,设置完以后我们做一个应用。是吧,哎,咱们顺便把这个也给它设置了吧,这个keep demo1啊,在他这块里边啊,这个你要没找着,你就在这再搜索一下就行是吧,哎,大家这块呢,我们也给它设置成这个,我改一下。我这儿写成是20兆。嗯,它俩数不一样是吧,来应用一下啊行,看一个十兆,一个是20兆,好OK,接下来呢,咱们把这俩成绩呢,分别给咱们跑起来啊,先把第一个跑起来。然后第二个,哎,这不第一个嘛,好,第二个也跑起来。
13:00
行两个程序呢,都跑起来了,现在呢,就进入这个阻塞的一个环节了,不让我们这个进程呢结束行,那么接下来的话呢,咱们来看一下这个两个进程啊怎么看呢?哎,这个大家呢,也都有这样的一个工具在我们这个JDK。咱们呢,现在这个程序是不是都以这个八为主的啊,因为现在在公司当中,大家主体用的还都是GDK8是吧,前段时间呢,我也看了这个比重啊,这个八的比重呢,还是非常高的啊,排第一。啊,那么把它打开以后呢,在这个B目录下呢,大家都会有一个工具叫做解啊VM。啊,结果手VM啊,把它的双击一下,当然你在命令行启动也行啊,那在左边的话呢,我们是不是就能看到各自的这个PID了啊process啊,每一个进程,然后双击打开。哎,双击打开好这呢,我们就提前呢,先用一下啊,从这个实用主义的角度来出发啊,嗯,这个工具呢,咱们先不详细的说,咱们用啥呢,咱就说啥。对吧,后边咱们调的时候呢,还要讲这个,哎,结果SOVM包括呢,还有其他的很多啊,那么在这呢,大家首先看在这个参数呢,我们设置的是不是就十兆,哎,你这个进程呢,是不是就20兆。
14:10
对吧,哎不一样啊,然后呢,先针对这个十兆呢,咱们看下这个细节,这个叫哎,我JC。啊,这个微手JC啊,这个这个微手应该念微手是吧,这个微JC当中呢,咱们看到了这里边这个大家现在一看可能有点眼花缭乱的啊,如果你首次呢,了解这个JC的,呃,了解这个对空间的话呢,看有点晕,因为这里边细节比较多,你先这样啊,哎,把这个数这个数这个数还是这个数呢加一起就构成了咱们的对空间。这一家是不是就十兆啊?没问题是吧,好,然后呢,打开咱们第二个这个例子哈,还是打开这个位数JC。嗯,你呢,把这个数这个这个这个把这几个呢加一起,加一起你看这俩是一兆,嗯,然后这个就是6.5兆,6.5加上二十二十二十兆啊。没问题是吧,哎,这呢就是我们这个程序啊,那这个程序呢,就比较清楚的,咱们能够证明就是这呢是两个进程,然后这个进程呢,它的堆是十兆,这个进程呢,它堆是20兆,是不是各自有一份啊。
15:10
没问题是吧,哎,那么对应回来呢,就是我们这里边,我把这个就关掉了啊。哎,就是我们这里边呢,说每一个GM事例,哎,它呢都对应的一个对空间,哎,先明确一下这个问题。啊行,我这呢先填一下。
我来说两句