00:00
好,下面呢,我们来看一下这个堆空间如何来设置它内存的一个大小。哎,如何来设置堆空间的一个内存的大小,以及呢,我们这个超出了堆空间以后呢,会报的一个错误啊,我们称为呢叫OMOK,那我们在前面呢,其实讲说每一个进程说各自呢拥有一个堆空间的时候呢,咱们实际上已经用过这两个指令了,这儿呢,我们就是具体的啊专门来说一下它啊那么如何去设置堆空间的大小呢?我们这儿呢,设置涉及到两个这个参数,一个呢是用来设置咱们这个堆去的一个起始,就是初始化的时候呢,它的一个内存大小,另外一个呢,是用来设置我们这个堆区内存的一个上限,就成为一个最大的内存,这呢是对应的这两个参数,这两个参数的话呢,它的全称的话呢,或者说它也等价于,其实谈不上说叫全称了哈,应该叫等价于,就是它跟我们使用这个指令呢,是一样子的啊,这个最大的这个空间呢,诶跟使用这个指令的设置呢,这个意思呢是一样子的,谈不上说是一个缩写了啊行,这是我们说的这个情况,也就是说呢,你用这个参数设置跟用这个参数设置呢,是完全一样的。
01:04
我们把这些呢,都称为咱们GM的一些运行参数,这呢等咱们后边讲这个性能优化的时候呢,咱们重点呢来说一说,像这些呢,这个运行参数这个符号是什么意思,到时候咱们重点的再剖析,现在的话呢,我们就是实用主义,实用主义对吧?我们现在讲到堆,下一章我们讲的方法区在后边的话,我们讲到这个GC的时候呢,咱们是用哪些,咱们就直接来用了,这个讲到哪块内容就直接来用,先不具体的展开来讲,这些参数呢,我们这个又分成几种情况,细节又是怎么写,咱们呢,先呃,不谈的那么细啊,是这样子的行,那么它呢是用来设置咱们这个叫初始的一个内存,这呢是一个最大的内存,好这块我们先在这儿呢,简单的再呃说明一下啊。台词啊,它呢是用来设置咱们这个叫对空间。它的一个诶初始内存大小这里边呢,我们一定要明确,这个所谓的对空间,我们在前边这个一节当中呢,已经说过了,这里的这个对空间呢,它就是指的呢,我们叫年轻代,加上我们的老年代,或者我们也称为呢叫新生代是吧,加上我们这个老年代,老年代呢,我们也称为叫养老贷,养老区是吧?这个呢叫年轻贷,年轻居新生区都可以,这个叫法呢,这个大家都能明白就行,就是不包括我们的原空间,或者说呢,GBK期当中,我们叫这个永久带是吧?这个大家一定要明确啊,然后呢,在这里边呢,我们这个杠X这呢是一个大写的,它呢,诶是咱们GM的运行参数。
02:39
这呢是GM的这个运行参数,这个注意是大S,然后这个MS它呢是这个一个缩写叫memory start,应该知道这意思了,对吧?这是我们的一个起始的一个内存的一个大小了,OK,注意这块呢,不是我们整个这个内存空间啊,只是我们这个堆空间的一个大小,那这是它,然后呢,我们又提到一个杠XMX是吧,这个它呢是用来设置堆空间,也仅仅是我们年形带和老年代的一个最大的内存大小。
03:15
OK,嗯,最大的一个内存大小行这呢,就是我们用这两个参数来进行设置,那大家呢,也可以通过我们这个这个。Oracle的这官网来进行查看,诶我们这有相对相对应的这个网址啊,你能看到这个网址呢,就能找进来,这呢就是咱们所有的这个参数,那后边的话呢,咱们讲到性能优化的时候呢,咱们再详细的展开来说这些参数啊CTRLX一下在这个位置呢,我们可以进行一个设置,比如我就写一个杠XMX是吧,把这个输入这呢就能看到,直接呢,我们在这这个位置呢,后边就写了一个叫size。那怎么写呢?你看它呢,最初的这个初始化的这个单位呢,是叫做字节,大家呢可以直接写,比如写个1024,就把这个S呢,你改成1024,或者你写这个数也行是吧,它表示的就是字节的意思,如果呢,你写这个小写的K或者是大写的K呢,表示的就是千字节,你要写这个小写的M或大写的M呢,表示的就是多少兆是吧?哎,这的话呢,就是我们说多少这个诶GB哎就这样的一个单位,也就说这个单位的话呢,它支持的是比较多的默认呢,你要不写单位呢,就是字节写上呢,就是KM或者是G啊也就是这样的这个情况,好这呢是我们说这个初始的,然后这个呢,这是最大的对吧?啊这个应该都比较清楚,行,那呃,这呢是我们说的第一个问题啊,就是大家呢,先去理解一下我们说这个如何去设置的这个参数。
04:34
啊,对。空间大小的这个参数,这是第一个问题,然后第二问题的话呢,我们谈一谈呢,就是所谓的这个叫在没有设置的时候呢,默认的,诶堆空间的一个大小对吧?诶默认时候呢,是什么情况呢?我们看一下这个PPT。啊,PPT在这写了,说呢,默认情况下,我们的这个初始内存呢,是物理内存的电脑这个内存的1/64,最大的内存呢,是我们物理内存的1/4,哎,咱们把这个呢直接诶拿过来,嗯诶点错了,用不着它是吧。
05:11
好,这个呢,大家清楚一下,那我下边呢,这不就写了个程序,咱们直接呢来跑一下就行,好我们如何获取一下咱们当前运行的这个虚拟机当中对应内存中的一个默认大小呢?以及最大的一个大小呢,是这样子的啊runtime runtime.get runtime这上就我们所谓的叫运行时是吧?诶大家可以把这个runtime这个实例呢,就当做是咱们这个找一下咱这个。上啊。整个这块的话呢,这就是咱们所谓的叫运行式数据区了,对吧?诶这个运行式数据区呢,其实它是一个单立的,就可以理解为咱们现在呢,就是通过这个runtime调用它这个方法获取到的唯一的单独的一个实例,这个单利模式嘛,就是我们当前这个运营实的一个环境啊,这个运营式环境获取一下这个total总的这个memory,这就是初始的一个大小,除以2024除以2024,这呢是一共多少多少的这个,诶我这用的单位是什么呀?叫兆是吧。
06:04
诶先出一个呢千字节,再出一个呢,就是多少兆吧,然后呢,获取它这个最大最内存就是max的一个memory,诶同样的得到这两个数,这呢就是我们看到一个在没有做任何参数设置的情况下的一个默认值,对吧?OK,那这块呢,我们先来这个runtime这块,呃,Runtime之前呢,先把我们这个程序呢,是不是先编译一下呀。没问题是吧,编译完以后呢,打开一下我们这个run啊,然后打开这个程序,呃,在这个位置呢,我们先找到咱当前的这个叫space initial啊OK1下行,这呢,我们没有写任何的参数,那就意味着咱们使用的就是默认情况,在默认情况下呢,我们看看它的一个大小,以及呢,我这块呢,直接呢就把这个初始的诶乘以64了,这个呢是乘以四的,然后把它换算成是这个GB,大家看一下这个数据的情况,好跑一下。OK,那大家看到了啊,这个数呢,我们就没有必要特意的去记了,甚至说呢,大家呢,运行起来以后呢,跟我这儿呢,也不一定一样,我的计算机看一下这个属性。诶在这能够显示,诶我本地的这个内存呢,是16GB,诶16GB所以呢,我们在运用完以后,大家看到这个数据,不管呢,是使用我们这个初始的内存,还是说这个最大的内存来看的话呢,这个是不是都基本上是接近于16GB的呀。
07:15
哎,有同学可能会想说,为什么不一样啊?哎,这个原因是什么呢?大家能想到吗?嗯,就是一方面呢,是咱们,呃,这个整个呢,物理上我这个内存呢,是16个GB,呃,但是呢,我我们实际在使用的时候呢,其实这个有很多这个数据呢,它要占就是一些必须要加载这些数据是吧?我们操作系统启动的时候呢,它要占据我16个GB,所以呢,在核算的时候呢,其实这里边或者换句话说啊,就是真正我们可用的这个内存空间,实际上呢,是不足16GB的,在你可用的这个空间里边,我们占据了1/4,或者是叫做诶1/16,哎或者叫做1/64,所以说呢,我们这样往回推的话呢,你会发现呢,它会小于我们这个16GB,就是我们可用的本身呢,其实就不足16GB是吧?诶,这是其一啊,那么另外一个原因的话呢,一会儿我们给大家解释,那一会呢,咱们自己设置的时候呢,我们去加一起算算这个数啊,你就知道什么意思了,为什么会这里边偏少一些是吧?诶咱们一会儿来解释啊好这呢是咱们说的第一个问题,需要大家记住的就是默认情况下,我们这个对空间的一个大小。
08:19
好,这是这个问题啊,那么下一个情况呢,就是咱们自己来啊,是不是来写一下这个参数啊,哎,自己来进行设置是吧?那自己设置的话呢,咱们就直接呢,在这个run当中找到这个iit啊,在这个位置我就可以写了,嗯,那就直接写杠MS,诶我们后边呢,比如说设置一个稍微大一点啊600兆这个写小写的M,大写M呢,我们刚才看官方了,是不是都可以啊,然后空格一下杠XMX这个是小写的啊,然后呢,我们也设置成600兆行,那这里边呢,我们就设置涉及到一个问题,哎,我先把它复制一下啊,再做一个应用,OK。那这是我们这个手动设置。手动设置的话呢,大家注意到,你看我这里边儿是不是把这个初始的和最大的设置成一个值了。
09:03
对吧?哎,那么真正在开发中我们设置的时候呢,要把这两个数设置成一样的吗?或者我们操作的时候呢,通常会怎么去操作呢?这里边儿我们要说明一下啊,在开发中建议呢,咱们把这个哎初始内存。啊,建议将初始堆内存和这个A最大的这个堆内存设置成一样的值。你看相同的一个值,大家能想一想说这个原因是什么吗?啊,你看是不是这样子的啊,就是说我们初始呢,要设置了一个值之后呢,如果对对空间不够的话,我们是不是要不断的给它去扩容啊,哎,给它去扩,然后不够的话呢,再去扩,然后再扩,一直达到我们这个,如果你还需要啊,可能会达到上限了啊,然后呢,这个我们这个去使用内存也有可能你没达到上限,那么后续的话呢,这个内存如果用不着,它是不是也会不断的往下去降是吧?那么大家想一下这个问题哈,我们如果在这个服务器当中去使用的时候。
10:02
啊,堆空间的话呢,我们不断的去扩容,那扩容呢,是它的增长方面,它是不是在你空闲的时候呢,也要把这个堆空间呢,给你去做释放呀,那如果是频繁的这个扩容和释放的话呢,是不是就会造成我们不必要的这个系统的一个压力。对吧,诶,所以呢,在线上生产环境当中啊,通常咱们都会把这个初始的对内存和最大的对内存呢,设置成同样的值啊,避免呢,就是这个JC啊,在这个JC之后呢,咱们去调整这个对应的大小,再造成这个系统的一个额外的压力啊这样,那其实类似的这个情况呢,大家也会去想这个什么呀,叫做线程池是吧。呃,线程池还有我们叫数据库连接池,就是在设置一个初始值之后呢,如果不够呢,我们会不断的去扩,然后呢,当空闲的时候呢,这些呃,这个空闲的这些额外增加的这个线程的数量,或者说数据库连接的数量也会给你销毁掉啊,其实这呢也是一些浪费,那在这个内存这块呢,因为又涉及到这个JC嘛啊,不断的去JCJC的本身呢,就挺耗费我们这个用户线上的一个占用啊,这个资源的一个占用,那如果此时的话呢,呃,在JC完以后,空间降低了,你再把这个对空间这个有多用的那些呢,再给它砍掉,真的势必还是会呃影响到我们程序性能的啊,所以建议呢,大家就把这两个设置成一样的值好了,设置完了是吧,那设置完以后的话呢,我们这时候呢,你做个运行的话呢,这个就不用参照了吧。
11:23
这时候咱们再看这个数就没有意义了,对吧,咱们就看一下当前这个初始的和最大的变成多少了。OK,那这里边大家也会看到,诶,怎么数有点小是吧?哎,我们明明设置的是600,咱们这里边看到呢,好像不是600了,是这意思吧,好,那怎么解释这个问题啊,这个我们就看一下啊,这个数怎么算出来的是吧?哎,这个数怎么算出来的,那怎么来看这个问题呢?我们通过两种方式来看,来教大一下啊,通过两种方式,首先呢,我们把这个打开。诶,我先把这个打开一下,这个也能看到,就是我们让这个程序呢,是不是睡这个睡了这个1000秒对吧?哎,就说白了,就让我们这个程序呢,不要这么快呢就结束啊这是这个问题,行,那此时呢,我们把单量先跑起来。
12:08
跑起来了,行,一会儿半会儿呢,他也结束不了啊,不用特别着急,此时的话呢,我们一种方式呢,是通过这个命令行,诶这个呢,又是咱们后边要讲的这个性能优化当中给大家要讲的这个命令行,咱们这块呢,为了说明问题,提前呢用一用,首先呢,在这我们输一个叫呃,GPS啊一回撤这个GPS这个指令的话呢,也是咱们JDKB目录下的一个指令,这呢我就不打开看了啊嗯,因为咱们配的环境变量,所以就直接可以用嘛,这个变量呢,它能够查看当前程序运行的这个进程,其中呢,我们这个,呃,刚才启动的这个程序是不是9228呀,OK,然后下边呢,我们再使用一个呢,叫j state。啊叫做这个j state j state是干什么的呢?它呢是用来是用来查看咱们这个GM在这个JC的时候呢,这个统计信息,诶显示一下咱们,呃,各个你想看的这个进程,它的一个内存使用情况,比如说我这儿呢,就想看下这个JC啊9228,哎这个程这个进程,哎,它的一个内存使用的情况啊一回车好这就出来了,那出来以后呢,大家看着可能稍微有点这个实力是吧,哎,我们把这个咱们需要的参数呢,给大家做个说明,未来这块计算方便呢,咱们直接调二个这个计算器啊。
13:24
好,这个计算机调出来了,然后呢,我们做个说明,这个咱们说了这个堆空间啊,是不是就是新生代加上老年代啊。没问题是吧,好,那么所谓的这个老年代的话呢,其实就是这两。哎,这俩老嘛,是不是就这old呀?没问题是吧,那这个OC跟ou是什么意思啊,这个OC啊,这个它表示的就是总量的意思,Ou呢,U就是used,就是你使用了多少,那这里边儿咱们没有使用这个老年代。是吧,哎,那这呢就是记这个数就行,那么前面这块呢,我们说这个新声代,它是不是又细分成啊叫伊甸园区,这个叫SURVIVVAL0区,SURVIVAL1区是这意思吧,啊由这三部分构成,所以呢,我们就看到前面一共有六项,这呢就是咱们描述的这个叫呃,伊甸园区。
14:06
啊,也是总量和它使用了多少,前面呢这呢就是S0S1的这个问题了,嗯,S0的S1的啊这是他们这个总量,这呢是他俩使用了多少行,那这块呢,咱们要做的事是不是就把这几个数给它加一下就行,25600是吧,那我就在这加了啊25600加上一个256。零零,就是我把这个数和这个数再加上我们这个这个伊甸园区的这个总量是吧,153600。好这块呢,我们加完以后呢,是相当于把新生代呢都加完了,然后再把这个OC就是我们这个老年代呢,再加一下啊。嗯,老年代409600。好,做一个回车,哎,这个数呢,咱们再去除以一下,哎,1024啊一回车好,大家能看到这个数是不是就600啊。没问题吧,哎,这就600,那我们这呢,算出来是600,怎么在这算的是这个A57,呃,575呢是吧,少25兆啊,怎么这块有问题呢,什么原因造成的呀。
15:12
啊,什么原因造成的,大家能想到吗?哎,来这个,因为我是录视频了啊,没办法给大家做交互了,我这块来给大家讲啊,大家你看这个数啊,我把这个25600。零零,然后呢,我加上一下,我就算一个啊,另外一个我就不算了,然后再加上咱们这个叫153600是吧,然后咱们再加上这个叫409600。哎,我坐个回车。那然后呢,我们再除以一个1024赶一回车,诶大家是不是看到就575哈,说你这个数是不是对的,哎,是不是这个就就会碰这个数啊,肯定不是嘛,那为什么我们这时候算下来是575,而这块儿呢,显示的也是575是吧?啥意思呢?诶这个原因是这样子的哈,就是啊,如果有同学呢,提前懂这个知识的话呢,应该能明白啊也是咱们一会儿要说的就是这呢叫一点园区,这呢叫S外零区,S外一区。
16:07
啊,就是这两个区域的话呢,实际上咱们真正要存对象的话呢,伊甸园区能创能放这个SURVIVAL0或者是SURVIVAL1,他俩呢只能二选一的去用,这是主要因为涉及到咱们垃圾回收这块呢,他们用的这叫复制算法,也就是呢,他俩始终有一个空间呢,是空的是吧,那我们能够放对象的呢,只能是呃,伊甸园区加上一个survivor区,所以呢,就没有算另外一个。又没有算另外一个,所以导致呢,你看刚才我们在这个呃,Idea当中算的是575,而事实上呢,咱们这块也算了,是不是就是600啊。哎,这个问题对吧,那另外呢,大家也能够理解,为什么咱们刚才呢,去算这个系统的时候呢,是不是相应的算出来这个数,你拿着这个诶575类似于这个数,再去乘以这个64等等,得到的结果是不是也自然而然的就会比较小啊,哎,能够明白是吧?好,这是这个情况啊,嗯,这是咱们查看的一种方式。
17:03
啊,这呢是一个呃,设置的方式啊,然后下边我写一个这个四啊如何去查看哟。哎,如何呢,去查看我们这个,呃,设置的这个参数,这呢我讲两种方式啊,方式一,诶刚才呢,咱们是用到了一个,诶叫JPS是吧,使用它呢,来查看咱们当前这个进程,另外呢,又用了一个,这样我就不写这么细了啊j state,诶然后杠JC,然后再使用我们这个进程。呃,进进成这个ID是吧,哎,就可以了啊行这呢是我们查看这个方式一,然后还可以使用一种比较简便的这个方式二。方程二的话呢,就是我们再加个参数,嗯,就是。这个英文格式加的print j c details,后续的话呢,咱们还是要经常会用这个参数的啊好,把这个呢,我们CTRLC一下放到咱们当前的这个,嗯,程序当中,在这后边啊,CTRLV加上咱们这个参数,就是打印一下咱们这个JC过程中的这些细节。
18:12
那我们做一个OK,这个时候呢,大家把这个就去掉了,你要不去掉的话呢,就是我们这个打印这个垃圾回收的这个细节的话,包括我们这个内存的使用情况啊,它呢是基于咱们程序执行完以后,你要是这块保保留这个1000秒的话呢,这个程序这个你等它执行完了才显示出来,这就不知道猴年马月了是吧,我们把它呢先注释一下啊,注释完以后的话呢,我们再去执行这个程序。诶好,大家来看这呢,是不是就列举出来了,咱们当前占用的这个情况对吧?嗯,因为呢,咱们现在呢,是在看一眼啊,是不是在这个JPK8当中我们跑的是吧?这呢是我们这个运行的这个环境哈,所以说此时我们看到的这个叫me space,咱们在上一节当中呢,说这个在JPK7当中真的叫嗯。
19:01
Permanent是吧,就是我们说的这叫永久贷啊,诶我就不演示这个七了,因为本身七也好八也好,本身算对空间的时候根本就没有考虑它。对吧,所以就不用管了啊,我们呢,主要关注的其实就是上边这个区域。啊,这个呢,就是我们后边呢,也会给大家去讲这个具体的JC日志分析啊,所以先不用着急,现在咱们还是实用主义啊,看看咱们这个主要想读的是哪几个数据。这呢就叫新生代,这个呢是叫老年代409600啊,如果大家你还有印象的话啊,看一下我们刚才这个还好,咱们是没有关啊在这里边啊,这个方便起见,我这么着一下吧,诶有同学说,诶后边是什么,后边咱们这个呢,就是涉及到这个,毕竟刚刚咱们用的这个指令是不是叫JC啊,后边就是这个新生代的这个,呃,JC,还有我们老年代这个for j c young j c,他们这个发生的次数。那这个咱们现在先不用关注啊,所以呢就忽略掉了啊行,把这个参数呢,我先这给大家盯了一下啊,然后大家来这做一个对比,就是这呢409600,是不是跟咱们标的这个数呢,是一样子的啊没问题是吧?诶就是诶都是老年代啊,然后这个新生代的话呢,这这153600,哎153600就它呗,然后这呢是256002560,诶嗯,刚才少少占个零二啊没过来,然后这呢也是256002560是不是完全一样啊,所以我们这儿呢,就是使用不同的方式来进行查看啊,稍微有一个细节需要注意。
20:26
大家看这这呢叫新生带说呢总大小呢是这么多,你看这个数,这个数咋算的啊。好,我们现在再算一下153600。然后我们加上一个25000。好,我一回撤是不是就是179200啊,这个179200,你注意我刚才是不是就只加了一个叫叫survival区,这叫from区或to区都可以哈,就是它的这个别名了,诶我们只加了一个,还是刚才解释的那个意思,就是我们整个这个新生代啊,他认为你有一个这个幸存者区啊,它一定是不放数据的,所以这里边呢,算这个total的时候呢,就没有考虑说,诶算两份这个幸存者区了,只算了一份。
21:08
啊,这个具体细节大家如果还有蒙的话呢,咱们后续呢,去讲这个对象真正存储的这个过程,大家呢,就彻底的就弄清楚了,好那我这儿呢,就从两个不同的角度呢,哎,大家呢说清楚了,我们这个诶初始的堆内存和最大堆内存如何去设置如何呢去查看,好这个我们就说到这儿。
我来说两句