00:00
那讲完这个TLB以后呢,咱们基本上关于这章的内容啊,咱们差不多也是到这个收尾的阶段啊,那最后呢,咱们把这个堆空间参数的设置呢,做一个小结,那在很多这个大厂的面试题当中啊,也确实会问到啊问我们这个GM在运行的时候呢,我们通常呢,哎设置的一些参数,那这些参数的话呢,在我们这个内存空间这块呢,咱们主要呢是在这个堆空间当中,哎设置呢,设置的呢,相对来说是多一些啊,当然呢,咱们在这个方法区呢,后边还会讲一些这个参数的设置啊,那另外的话呢,就是咱们提到这个垃圾回收使用呢,具体的什么样的垃圾回收器啊,到时候呢,咱们还会有一些参数,诶是这样子的,包括调用的话呢,也会有一些参数啊,那咱这块呢,针对这个堆空间这块,咱们把常用的这些参数呢,给大家做一个小结。那其中呢,有一些参数呢,咱们已经见过了啊,这呢咱们就做一个简单说明,那对于没有见过的这个呢,我们做一个详细的一个解释,OK,那首先说一下我们这个参数,这个在官网当中呢,其实已经给我们提供了一个专门的链接,大家呢,去查看所有的这个参数啊,我这块呢,其实也已经提前都打开过了是吧,就是我们这个页面啊,这个页面当中大家往下看,就是我们见到的所有的这些参数,当然呢,支持啊,咱们CTRLF呢进行一个搜索是吧?诶我们想搜索的话,比如说诶叉MS。
01:15
那这个呢,我们就找到了相关的它的一个呃,参数的意思,以及呢,我们如何去使用这个参数,那整个这个参数的话呢,大概是有600多个,那很显然的话呢,我们不可能每一个参数呢都去了解,都去熟悉,就好比是呢,我们看这个API一样,咱们Java的API呢,大家用的可能已经常用的这些已经很熟了,但是呢,我们始终会有一些API,我们自始至终也从来没有使用过,包括呢一些异常呢,我们也从来没有出现过,对吧?所以说呢,就是我们没有必要呢,把所有的这些参数呢都整明白,我们只需要关注呢,咱们在开发当中常用的一些参数就可以了。啊,那这呢,我们就来看一看常用的参数都有哪些行,那这呢,我把这些参数呢,咱都粘到对应的这个代码的这个位置啊,我这写了一个叫这个hip xx test啊这呢咱主要来测试一下对空间中常用的参数。
02:09
OK,那这呢,我就CTRLV一下啊,直接把它那个列出来行,下边呢,还有这个第二波,嗯,把这个呢,我们也直接给大家CTRLC一下。好,这呢我们就放到这儿了,行,那么通过咱们这个代码的话呢,我们来说明一下啊,其实这块代码的话呢,我们主要呢,也写不了什么代码,主要是借着我们这个程序呢,咱们把这个参数呢,来给大家做一个说明,好那就按照这个顺序呢,咱们来讲解啊,首先来看一下这个呢叫print flex initial啊print flex flex呢final。一个呢,就是一个初始化的,一个呢是最终的什么意思呢?就是来打印一下咱们所有这个参数的一些默认值,这呢是打印它最终的一个值,那默认值跟最终值的区别呢,就是我们有一些参数呢,可能使用的不是默认值,而是把它呢做了一个修改,那这呢就是能够显出显然呢你修改以后的,而这个呢,就是你如果修改的话呢,呃,查看默认值的话呢,还是原来的那个默认值,诶就是这样个意思,好,那我们举个例子啊,就比如说在我们当前这个程序当中,首先的话呢,我们把这个参数呢,诶给它CTRLC,诶咱们在这个run这块呢,进行一个演示啊打开。
03:14
我们呢,首先来看的是咱们关于这个叫呃he X,针对我们这个程序呢,我把这个参数呢粘到这,顺便的话呢,我再多写一个啊,多写一个,咱们前面来设置这个EDH区和survivor取他们的一个比例的,咱们用的叫啊survivor啊,Raio啊,这个值呢,默认的是八,好,我这块呢改一下,比如呢,我改成是一个五啊举个例子,行,我们这呢,APP apply啊OK一下,此时呢我们做一个运行。好,那运行完以后呢,咱们就能看到呢,所有的这些我们见到的这个GM这些参数的一些默认值,注意我们这块呢,看到的是默认值,咱呢就直接找刚才呢,设置了一个叫survival ratio。啊OK,那这块呢,大家看到默认这个质量是八对吧?哎,这呢,就是我们看到所有的这个参数的一些默认值,咱们前面的话呢,其实给大家呢,也讲过啊,也看过具体的一些参数的默认值,咱用的呢,不是这个指令啊,其实咱们这个值呢,类似于是这个是吧,看它这个目前的这个值是多少,咱用的是什么呀,大家还记得吗。
04:19
那就是我们具体查看这个某个这个参参数的这个指令,嗯,咱呢,其实是这样的啊先呢,是不是使用这个GPS通过他呢,来查看我们当前程序中的进程是吧?呃,当前运行的。啊,运行中的这个进程,那这呢,就找到我们想查看的是具体哪个应用程序,呃,这个或者叫哪个进程当中的这个,呃,参数的默认值,然后接下来呢,咱们使用的是这个操作啊,诶这个呢叫基因ER还记得吧,然后呢叫flag,那在后边呢,就是我们要查询这个参数,比如说呢,咱们现在想查询的叫做survivor。
05:05
啊,这个raal这样,然后在后边呢,就写上我们这个进程号,进程的一个ID,那这样的话呢,我们就查到查询到具体这个进程当中的这个参数的设置的值是多少啊是这样子的行,那我们呢,呃说这个值呢,它其实更相相当于是我们这样一个指令啊那我们下边来看一下这个指令是什么意思啊,诶我把这个呢参数直接呢CTRLC一下,诶换到我们。参数设置里边把这个呢给它去掉啊,粘过来做一个替换啊,然后再做一个应用,那此时呢,我们再做一个执行。好,那咱们呢,还去找上面这个叫survivor。Survival ratio。嗯,在这是吧,好,大家呢,能看到这个值呢,就是五,哎,刚才呢,我们也设置这个值的,只不过呢,你看到还是默认值,所以呢,它是八,这个五,前面呢,它是叫冒号,等于这个呢,就意味着我们重新做过赋值,就不再是你默认的那个值啊OK,行,这呢是我们指的两个这个指令啊,大家呢去关注一下,然后在下边这块呢,呃,咱前边已经讲过了,它呢是来设置咱们这个堆空间的一个默认的,诶不是默认的设置我们堆空间的一个初始的一个内存,呃,默认情况下呢,是物理内存的1/64啊,这里是堆空间的一个最大内存,默认的是1/4,对吧?这呢是设置这个新生代的一个大小。
06:26
OK啊嗯,行,那这几个参数的话呢,咱相对来说都比较熟了啊,然后下边这个呢,是设置这个新生代和老年代在对空间中的一个占比,也说过了,默认值呢,是不是二啊,哎,就呃这个新生代是占一,老年代占二,总共呢是占1/3是吧,新生代老年代2/3,然后这个呢,是设置我们这个呃,伊甸园区和我们survivor这个区的一个比例大小的。啊,这个没问题,这个默认值量是棒啊,那这个呢,咱们多说一句啊,比如说我们设置这个比例的时候,在我们这个new ratio已经确定的情况下,包括呢,我们这个对空间整个已经确定的情况下呢,我们这个survivor ratio这个设置的大或小有什么影响呢?啊,比如说这是我们这个新生代的一个大小是吧,如果我们要设置的这个叫呃,这个伊甸园区要是偏大的话啊,或者我比这个还要再再大一些是吧,就是我们设置这个伊甸园区,如果要是比较大的话。
07:20
IG呢,就是我们这个幸存者零区或者幸存者一区呢,是不是特别小啊,那这种情况下呢,会导致什么样的问题呢。大家想一想啊,那如果理想情况下呢,就是我们这个对象呢,放到这个异地园区的时候呢,在进行这个样JC的时候,所有的这个对象都被回收了,这是我们说是最理想的状态啊,没有这个呃,要晋升到我们的这个survivor区的啊,这个对象这是最理想的,但事实上呢,肯定不可能总会有一些对象呢,是不是要这个呃,存放到就是还存活着啊,存放到我们这个survivor区,它的age呢,也变成是一。那由于我们这个survivor区域,大家想如果设置的是比较小的话,那就会导致我们这个survivval区可以放的这个对象呢,是不是相对来说就比较少,那如果接下来呢,我们这个呃,再往这个呃伊甸园区放对象的话呢,那很容易呢,是不是我们这个对象呢?呃,再往这个survivval区放的话呢,Survivval区就已经沉不下了,也就是说很容易VI区呢就满了,那这时候呢,我们就要考虑的是把这个你这个没有被回收的这个数据呢,直接就要放到这个old区了。
08:21
也是我们说的这个老年代。对吧,啊,那这样的话呢,会有什么问题呢?就是如果说伊甸园区过大的话。啊,我说呀,是不是会导致咱们呃说这个叫mini j c,它就失去意义了啊,因为本来的话呢,我们这个呃伊甸园区呢,嗯,它在进行米JC的时候,我们survivor区这块也会进行一个垃圾回收,相当于让我们这对象呢,始终呢,是不是就在我们这个新生代这块不断的去回收,是吧,而你这块呢,比较早的没有达到这个预值15,就直接呢去到老年代了,那我们这个M这些呢,其实意义就不大了。啊,那这块呢,就后来就主要执行我们的叫major这些了,是吧,这是一个啊另外的话呢,我们这个分带的主要目的呢,是不是让我们的对象尽可能的先存在咱们这个新生代,然后老年代这块呢,是你达到一定情况以后再去,那现在的话呢,是不是分代的这个意义呢,也更加的弱是吧?哎,属于这样情况啊,那再换一个场景,那如果说我们这个在新生态确定的情况下呢,我们这个一六园区呢,设置的不够大。
09:20
我们这个survivor区呢,设置的要比较大,这个时候又会出现什么样的问题呢?想想对吧,哎,那这时候问题就成了咱们这个样JC或者叫mini j c,它触发的一个这个条件呢,就是我们这个伊甸园区呢,满的时候,或者说空间不足的时候呢,我们要出发。那这就意味着我们一定园区如果比较小,咱们这个样JC或者叫mirror j c出现的频率呢,是不是更高啊。哎,频率呢就变高了,那频率要改变高的话呢,很显然它会影响我们这个用户进程,导致我们这个STW这个时间,总体时间呢,是不是就变多了,哎这呢就影响我们整体这个性能是吧?哎,这就这样一个解释啊啊就是大家呢,能够通过刚才解释呢,能够理解这个事儿啊就行,就是整个呢,大家能够,诶对这几个参数呢,能够有个理解,咱们后边讲调优的话呢,如果从这个JC的角度,咱们尽可能的要降低的就是关于垃圾回收的这个频率是吧?哎,那我相当于呢,你间接的就提升了这个用户线程执行的一个比例了。
10:21
啊,导致我们的吞吐量呢,就能够增加啊,那这时候呢,我们就要看一下这个参数怎么去设置了,没有一个统一的标准啊,我们都得是具体问题具体分析啊行,下一个呢,叫max,呃,Turning呃,Thhold就是我们设置一下这个新生代的垃圾回收的最大年龄,咱们说默认情况下呢,这个值是15是吧?哎,这个就不多说了啊,一般呢,咱们这个值也就不过不过多的去做这个修改了。啊,那如果说你这个值修改的比较大,那尽可能的说白了,如果这个值比较大的话呢,说白了就是我们尽可能的是把这个对象呢,留在我们的这个新生代啊。哎,尽可能的留在这个新生代了啊,就成这样了,实际上呢,我们也没有必要给它设置的过早啊,你要设置的特别大的话呢,这个对象呢,始终不能够去竞升到老年代,导致我们这个survivor区其实也很容易的,是不是就满了,所以呢,这个量也是适中就可以。
11:11
好在下边这块呢,叫print j c details,咱们后边讲JC的时候呢,还会用这个参数,那现在的话呢,我们使用了大家已经见到了好几个场景了,就是打印一下我们这个垃圾回收的一些详细信息。啊,一些详细信息,那么呃,下边这块呢,又提到两个简化的信息,这个大家了解一下就行,比如说叫print jc,没有这个details啊,这个呢,就是比较简化的一个操作了,举个例子哈,比如说我们还是使用刚才这个指令CTRLC,咱们呢,那会儿是不是演示了一个呃,具体的代码操作。嗯,找到我们刚才那会举的一个例子啊,比如就拿这个JC它来说,我们在这个里边。哎,设置一下这个参数。那找到他是吧,哎,我把这个呢,CR拿过来,嗯,这个。内存空间呢,我没有设置,咱们设置一下哈。
12:00
这个我来一个100吧。行,那么在这个堆空间是100兆的情况下呢,我们打印一下这个垃圾回收的这个细节,好做个OK,此时呢,我们做一个执行。好,这呢就是我们看到这个叫详细情况,上面呢是我们进行的一个呃,垃圾回收的记录啊,日志的记录,然后下边呢,就显示了我们最后呢,这个对空间中各个部分的一个数据的占用情况啊,中间的是我们报的这个异常行,那如果说我们把这个参数呢,给他做一个修改,那修改成呢,比如说我们这个参数啊,CTRLC一下。啊,回到这儿,咱们再做一个调整。改成它对吧,然后我们再做一个应用,OK,再跑一下。行,那这时候大家会看到上面呢,我们这个关于呃这些的一个日志呢,比之前呢,也短了一些,就是信息呢,也没有那么呃详细了,然后最后呢,也没有我们最后呃这个对空间中各个部分的一个记录啊,所以它就是一个简化的一个记录。
13:03
啊,是这个问题,那同样的话,这个指令也是一样,我就不演示了,这两个指令的话呢,它输出的效果呢,是一样子的,那咱们要用的话呢,是不是肯定要用这个,呃,打印的信息更完整更详细一些是吧?所以大家呢,就主要记住这个啊参数就可以了,Print j c details OK,然后呢,这就过了最后一个我们再提一下,这叫I handle promotion failure啊是否设置空间分配担保,咱们在前面讲这个,呃,叫什么内存分配策略的时候呢,提到过这个分配担保这个问题啊,当然呢,我们说这个讲到这个参数的时候呢,咱们提一下。好,那么关于这个参数呢,咱们做一个解释说明,大家呢,直接看我这段描述就可以了。哎,直接看这个描述就行,好来我们解释啊,它这个参数呢,我们影响的是什么。在我们发生这个mini这些之前。就是新生代这个垃圾回收之前,虚拟机啊,会检查老年代当中最大的可用的连续空间是不是大于新生代所有对象的总空间。
14:03
因为呢,我们进入mid j c要将这个新生代中的这个我这样画啊,这是新生代真上是老年代,我们要将新生代中这个对象啊,是不是要往这个老年代中去放,是吧?那我们先看一下你现在啊存在这些数据,这个大小呢,是不是大,呃,就是大于也好,小于也好啊就是这呢,我们是拿它判断是不是大于这个了,就我这儿呢,剩余的这个连续空间是不是比你这个数大,那如果要大的话呢,你这个最高最糟糕的情况下呢,就是这些数据呢,没有一个是垃圾,全部要拿过来,对吧?诶是这个意思,也就是说呢,老年代如果说这个是大于他的话呢,我们就,哎。此次的mini jc相当于就是安全的。对吧,它就是个安全的啊,就是你直接呢,操作没问题,就直接可以放过来,说白了就是我们这时候呢,就执行一个mid j c就行,然后如果要是小于的话,Ug就我们对空间这块,呃,这个老年代这块呢,呃不保险啊,这个不保险,这个我联系空间呢,比你这个呃占用的这个新生代这个空间啊,现在要小小的话怎么办呢?我们就要看一下这个刚才说到这个参数。
15:01
哎,叫空间分配担保是不是允许是失败的,那这个值呢,它是一个布尔型的,如果呢,你设置它的值是处。啊,如果是处的话呢,这时候怎么办啊,我们老年代接着要检查一下,老年代呢,最大可用的连续空间是不是大于这个力次晋升到老年代对象的一个平均大小。啊,历次进入到老年代对象的一个平均大小。能理解这个事儿吧,就是我们现在这个新生代用了这么多这个内存,这呢是我们这个老年代,然后新生代这块呢,比如说我们是有这个20兆,但是以前历次平均情况下呢,你只有15兆是要往这块放的,我们就拿这个平均数呢来说。就拿这个平均数来说,那如果说呢,咱们老年代现在空的这个空间比你这个15兆要多啊要多,那就意味着我们此时这个mini j c也是可以的,当然了,咱们说是存在一定的风险是吧,万一呢,它平均值是15,它比15就是高呢。对吧,哎,有这个问题啊,所以咱这呢是一个概率的问题,就是尝试呢进行me jc,但是依然呢,是有一定的风险。
16:06
啊,这个然后如果要是小于呢,就是如果我们这个空间呢,它是一个12兆呢,12兆比这个15兆小,那沿IG呢,就是我们以平均概率上来讲的话呢,这个我们很有可能这个进行密这些以后,诶平均的话呢,有15兆要过来,但是你要过来的话,我这个堆空间是不是,呃,这个老年代呢,是不是放不下呀。啊,那老年代要放不下,咱们要进行这个major j c,所以说呢,咱这里写了,如果你要发现小于的话呢,就干脆直接呢,我们进行一次four c。新生贷,行业贷都回收一下。就是这个问题是吧,哎这呢是我们说这个值日处,那如果你这个值是false呢,哎,False的话呢,直接我们就进行for这些了,就不再去检查这个平均情况。啊,注意啊,大家呢,捋一下我们这个过程啊,好,那捋完以后的话,我们紧着再说一句话,就是说在JDK6UPDATE24,就是在更新了第24个小版本之后,或者的话呢,大家干脆呢,你就直接记一下,咱们叫做JDK7也行啊,就是小版本,有时候经常我们不会记得那么细了,是这意思吧,大家呢,也可以记成JDK7,就是JDK7集之后呢,咱们这个参数呢,就失效了。
17:12
就不会再影响咱们是不是进行这个空间分配担保了。啊,其实这块呢,呃,这样给大家解释啊,你就把这个值你就理解成是个处就得了。这个参数呢,就没有影响了,你就把它看成个处。啊,这个过程呢,还是这样走,那言外之呢,就是说如果呢,你检查老年带的这个最大可用的连续空间是大于新生带这个最像总空间呢,直接就MGC带。对吧,哎,或者的话呢,你发现这个老年代最大可用的这个联续空间呢,大于例次进入到老年代这个对象的一个平均大小,是不是我们也进行这个M这些啊,哎,就是我这里边写的这句话。就是这句话,就是这句话,然后这句话就是我们的这句话是吧,哎,有这个一一对应关系。啊,那如果呢,是这两种情况之一的话呢,咱们就进行MJC,那如果不是这两种情况,咱们就进行for g c,哎,说白了呢,大家就把这个参数呢,看成是一个true就行。
18:08
啊,这呢,就是我们是否使用这个叫诶空间分配担保这个策略,就是咱们上面呢提到的这个问题。诶,空间分配担保啊,这个事情行,那么关于咱们这个堆空间中常见的这个参数啊,咱们呢,就给大家说这么多,哎后续的话呢,咱们还有其他在垃圾回收方面,在性能调优方面,我们还会有一些参数,大家呢,及时的去总结啊,及时的去积累,那么在面试当中啊,也确实好几个大厂呢,都常爱问,哎,常用的参数有哪些?哎通过这个呢,来看一下你是不是在开发中使用过啊是这样的一个道理。
我来说两句