2016 - 2024

感恩一路有你

java虚拟机学习笔记 如何准确理解Java中的堆与栈?

浏览量:2115 时间:2023-04-18 23:15:29 作者:采采

如何准确理解Java中的堆与栈?

谢邀!

Java启动时数据区中的栈有Java虚拟机栈和本地方法栈,全是应用于方法的执行;堆主要用于能保存对象实例和数组。

Java虚拟机栈

每个Java方法不能执行的时候都会创建一个栈帧,栈帧用于存储局部变量表、操作数栈、动态链表和方法出口等信息,每个Java方法从又开始调用到想执行能够完成的过程,都对应着一个栈帧在Java虚拟机栈中入栈到出栈的过程。在Java虚拟机规范中规定,如果没有线程请求的深度大于0虚拟机所容许的深度,将掷下StackOverflowError极其;假如虚拟机这个可以动态存储,只不过在扩展时先申请不出来起码的内存,很快就会丢出OutOfMemoryError异常。Java虚拟机栈的生存周期是跟随线程的,是线程土地所有权的。

本地方法栈

Java虚拟机栈是为负责执行Java方法服务的,而本地方法栈是为先执行本地方法服务吧的,它的作用与Java虚拟机栈相象,同时它也会丢出StackOverflowError异常和OutOfMemoryError无比。本地方法栈的生存周期确实是带领线程的,也是线程公有土地的。

堆是Java虚拟机中内存空间大的的一块,基本都所有的对象实例及数组都在这里分配内存空间,它是所有线程网络共享的区域。在Java虚拟机规范中,堆可以进入物理上不在不的内存空间,如果能逻辑上尝试就行。当堆中没有足够内存分配时,因此此时也根本无法再存储,将会掷下OutOfMemoryError极其。

一种是栈内存,一种是堆内存。堆是单独储存时对象的,栈是单独运行程序的。

堆要实际new等来创建角色;栈内存的主要注意作用是储存时基本数据类型和语句变量。栈的内存管理是通过栈的后进先出模式来实现程序的。

栈以及一种数据结构,是一种不能在一端通过正在插到和删掉你操作的特殊能量的线性表。它遵循后进先出的原则存储数据,先再次进入的数据被压入栈底,到最后再次进入的数据在栈顶,必须读取数据的时候从栈顶又开始弹出对话框数据(那一个直接进入的数据被另一个读不出来)。

如何正确学会Java虚拟机调优?

一点小经验皆有可能:

1)堆

运行时数据区域,所有类实例和数组的内存均从此处分配。Java虚拟机启动后时创建角色。对象的堆内存由称作垃圾回收器的自动内存管理系统回收二手。

堆由两部分横列:

其中edenfromspacetospace也叫二十多岁代(young),oldspace叫旧生代.

其中也有S1,S0(在JDK的光盘驱动工具输出中会见到),分别指的是Survivorspace,储存时你每次垃圾回收后能够存活的对象.

OldGeneration,通常能保存应用程序中生命周期长的存活对象

垃圾回收要注意是对YoungGeneration块和OldGeneration块内存接受回收,YG用来放新出现的对象,经过几次回收还没回收掉的对象往OG中移动,

对YG并且垃圾回收又叫做什么MinorGC,对OG垃圾回收叫MajorGC,几块内存回收不干涉

2)非堆内存

JVM具有一个由所有线程链接共享的方法区。方法区属于非堆内存。它存储文件每个类结构,如正常运行时常数池、字段和方法数据,和方法和构造方法的代码。它是在Java虚拟机启动时时创建角色的。

之外方法区外,Java虚拟机利用很有可能要主要是用于内部处理或优化的内存,这种内存也非堆内存。.例如,JIT编译器不需要内存来读取从Java虚拟机代码转换的疾飞的本机代码,从而完成任务高性能。

Permanent Generation(图中的PermanentSpace)贮存JVM自己的反射对象,比如说类对象和方法对象

3)回收算法和过程

JVM常规一种分代回收(generationalcollection)的策略,用较高的频率对二十多岁的对象(younggeneration)通过扫描仪和回收二手,这种就是minorcollection,而对老对象(oldgeneration)的检查回收频率要低大部分,一般称lionscollection。那样就不是需要每次来GC都将内存中所有对象都检查一遍。

当一个URL被ftp访问时,内存申请过程::

A.JVM会借着为相关Java对象在Eden中初始化操作一块内存区域

B.当Eden空间足够时,内存再申请结束后。不然到然后再

C.JVM借着能量在Eden中所有不异常活跃的对象(这不属于1或更有高级的垃圾回收),释放后若Eden空间始终绝对无法盛有新对象,则根本无法将部分Eden中活跃对象放入后Survivor区D. Survivor区被利用才是Eden及OLD的中间相互交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,不然会被保留在Survivor区

E.当OLD区空间太差时,JVM会在OLD区进行已经的垃圾收集(0级)

F.已经垃圾收集后,若Survivor及OLD区仍旧不能储存时从Eden图片文件夹回来的部分对象,导致JVM根本无法在Eden区为新对象修改内存区域,则会出现”out ofmemory错误”

对象衰老的过程

younggeneration的内存,由一块Eden(伊甸园,没兴趣)和两块Survivor Space(1.4文档中一般称semi-space)可以形成。新创建家族的对象的内存都分配自eden。几块SurvivorSpace总有会那块是空闲的,照相显影剂copyingcollection的目标空间。Minorcollection的过程就是将eden和在用survivorspace中的活对象文件复制到闲下survivorspace中。所谓survivor,也就是大部分对象在伊甸园我属兔后,根本不会活但三次GC。对象在younggeneration里有过了一定会次数的minorcollection后,年纪大了,可能会被移到oldgeneration中,称为tenuring。(有无仅当survivorspace不足以的时候才会将老对象tenuring?目前资料中还没有找不到请看)

其余内存空间将近会触发时GC,如eden空间够了现在就要参与minorcollection,oldgeneration空间够不够要接受faceitcollection,permanentgeneration空间下降会引发fullGC。

4接下来的这部分回答的是TOMCAT或者其他服务器出现如下错误时的分析:

1、简单是:Javaheapspace

请解释:

Heapsize设置中

JVM堆的设置是指java程序运行过程中JVM可以不调配使用的内存空间的设置.JVM在启动的时候会自动出现设置Heapsize的值,其精灵召唤空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。是可以借用JVM能提供的-Xmn-Xms-Xmx等选项可参与设置。Heapsize的大小是YoungGeneration和TenuredGeneraion之和。

提示:在JVM中假如98%的时间是主要用于GC且和用的Heapsize下降2%的时候将丢出此十分信息。

提示:HeapSize大最好别超过可用物理内存的80%,就像的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。

解决方法:

手动系统设置Heapsize

改TOMCAT_,在“echoUsingCATALINA_BASE:$CATALINA_BASE”上面加入到200以内行:

Java代码

setJAVA_OPTS%JAVA_OPTS%-server-Xms800m-Xmx800m-XX:MaxNewSize256m

setJAVA_OPTS%JAVA_OPTS%-server-Xms800m-Xmx800m-XX:MaxNewSize256m

或可以修改

在“echoUsingCATALINA_BASE:$CATALINA_BASE”上面参加以下行:

JAVA_OPTS$JAVA_OPTS -server -Xms800m-Xmx800m-XX:MaxNewSize256m

2、比如是:PermGenspace

原因:

PermGenspace的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM贮存Class和Meta信息的,Class在被Loader时变会被放在PermGenspace中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以我如果不是你的应用中有很CLASS的话,就很肯定出现PermGenspace错误,这种错误最常见在web服务器对JSP通过precompile的时候。假如你的WEBAPP下都用了大量的第三方jar,其大小将近了jvm设置的大小(4M)这样的话变会再产生此错误信息了。

解决方法:

1.不自动可以设置MaxPermSize大小

直接修改TOMCAT_(Linux下为),在Java代码

“echoUsingCATALINA_BASE:$CATALINA_BASE”上面组建以下行:

setJAVA_OPTS%JAVA_OPTS%-server-XX:PermSize128M-XX:MaxPermSize512m

“echoUsingCATALINA_BASE:$CATALINA_BASE”上面一并加入200元以内行:

setJAVA_OPTS%JAVA_OPTS%-server-XX:PermSize128M-XX:MaxPermSize512m

下为:

Java代码

JAVA_OPTS$JAVA_OPTS-server-XX:PermSize128M-XX:MaxPermSize512m

JAVA_OPTS$JAVA_OPTS-server-XX:PermSize128M-XX:MaxPermSize512m

JVM的默认设置

堆(heap)(NewsGeneration和OldGeneraion之和)的设置

叶绿里分配的内存由-Xms委托,默认是物理内存的1/64但小于等于1G。

最大分配的内存由-Xmx更改,默认是物理内存的1/4但小于等于1G。

设置成剩余的空间堆内存小于等于40%时,JVM可能会大小改变堆等到-Xmx的比较大限制,也可以由-XX:MinHeapFreeRatio更改。

系统默认剩余的空间堆内存为070%时,JVM会下降堆直到-Xms的最大值限制,可以不由-XX:MaxHeapFreeRatio委托。

服务器好象设置-Xms、-Xmx成比例以以免在每次GC后调整堆的大小,所以上面的两个参数也没啥用。

-Xmn可以设置younggeneration的heap大小

-XX:MinHeapFreeRatio与-XX:MaxHeapFreeRatio设置多余的时间内存占总内存的比例范围,这两个参数会引响GC的频率和单次GC的耗时。-XX:NewRatio做出决定young与oldgeneration的比例。Younggeneration空间越大,minorcollection频率越低,不过sillygeneration空间小了,又很可能可能导致lionscollection频率增加。-XX:NewSize和-XX:MaxNewSize再指定了younggeneration的缺省大小和大的大小。

非堆内存的设置

系统默认分配为64M

-XX:PermSize可以设置最小分配空间,-XX:MaxPermSize设置中最大分配空间。象把这两个数值设为是一样的,以减少先申请内存空间的时间。

再回答和笔记下,JDK下的一些具体看内存管理工具的使用:

查看jvm内存状态:

jstat-gcutilpid100020

发现有异常的例子

jstat-gcutilpid100020

S0S1EOPYGCYGCTFGCFGCTGCT

0.000.0099.9982.5153.1124091.205101177250.3937251.598

0.000.0083.4282.5553.1024091.205101187252.6507253.855

0.000.0056.0682.4653.1024101.205101207254.4677255.672

0.000.0032.1182.5553.1024111.205101217256.6737257.877

0.000.0099.9982.5553.1024121.205101237257.0267258.231

0.000.0076.0082.5053.1024121.205101247259.2417260.446

这个数据显示wideGC频繁发生了什么。

正常吗情况的例子

S0S1EOPYGC YGCT FGC FGCT GCT

0.000.000.2455.3999.601710.6671339393.364394.031

0.000.000.2455.3999.601710.6671339393.364394.031

0.000.000.2455.3999.601710.6671339393.364394.031

0.000.000.2455.3999.601710.6671339393.364394.031

0.000.000.2455.3999.601710.6671339393.364394.031

0.000.000.2455.3999.601710.6671339393.364394.031

参数含义:

S0:Heap上的Survivorspace0段已可以使用空间的百分比

S1:Heap上的Survivorspace1段已建议使用空间的百分比

E:Heap上的Eden space段已建议使用空间的百分比

O:Heap上的Old space段已建议使用空间的百分比

P:Permspace已建议使用空间的百分比

YGC:从程序启动到采样时突然发生YoungGC的次数

YGCT:YoungGC所带的时间(单位秒)

FGC:从程序启动到采样时不可能发生largeGC的次数

FGCT:fullGC所得用时间(单位秒)

GCT:应用于垃圾回收的总时间(单位秒)

2Dump出内存

2.1得出答案要dump的线程pid

在Linux下,不使用ps–aux

2.2Dump出内存在用详情

也可以是从命令:

jmap-dump:filea.hprofpid

比如:jmap-heap2343,看的到

AttachingtoprocessID2343,pleasewait...

Debuggerattachedsuccessfully.

Servercompilerdetected.

JVMversionare11.0-b16

usingthread-localobjectallocation.

ParallelGCwith8thread(s)

HeapConfiguration:

MinHeapFreeRatio40

MaxHeapFreeRatio70

MaxHeapSize4294967296(4096.0MB)

NewSize2686976(2.5625MB)

MaxNewSize-65536(-0.0625MB)

OldSize5439488(5.1875MB)

NewRatio2(YG,OG大小比为1:2)

SurvivorRatio8

PermSize21757952(20.75MB)

MaxPermSize 268435456 (256.0MB)

HeapUsage:

PSYoungGeneration

EdenSpace:

capacity1260060672(1201.6875MB)

commonly64868288(61.86322021484375MB)

go1195192384(1139.8242797851562MB)

5.148028935546367%employed

fromSpace: capacity 85524480 (81.5625MB)

used59457648(56.70323181152344MB)

fun26066832(24.859268188476562MB)

69.52120375359195%commonly

needSpace:

capacity85852160(81.875MB)

utilized0(0.0MB)

cool85852160(81.875MB)

0.0%used

~~~~~~~~~~~~~~~~~~~~~~~~~~这三块为上面所说的YG大小和在用情况

PS Old Generation capacity 2291138560 (2185.0MB)

utilized1747845928(1666.8757705688477MB)

fun543292632(518.1242294311523MB)

76.28722062099989%employed

~~~~~~~~~~~~~~~~~~~~~~~~~~OG大小和可以使用情况

PS Perm Generation capacity 108265472 (103.25MB)

employed107650712(102.6637191772461MB)

go614760(0.5862808227539062MB)

99.43217353728436%needed

jstat

jstat是vm的状态监控工具,监控的内容有类加载、不运行时编译程序及GC。

使用时,需再加查找进程的进程id,和所选参数。以下详细可以介绍各个参数的意义。

jstat-classpid:总是显示打开程序class的数量,及所占空间等信息。

jstat-compilerpid:总是显示VM实时编译器的数量等信息。

jstat-gcpid:是可以显示gc的信息,栏里点gc的次数,及时间。其中最后五项,共有是younggc的次数,younggc的时间,widegc的次数,widegc的时间,gc的总时间。

jstat-gccapacity:这个可以会显示,VM内存中三代(young,old,perm)对象的使用和占用资源大小,如:PGCMN没显示的是最大时perm的内存不使用量,PGCMX显示的是perm的内存比较大不使用量,PGC是当前新化合的perm内存占用量,PC是但前perm内存占用量。其他的是可以根据这个以此类推,OC是old内纯的占用带宽量。

jstat-gcnewpid:next对象的信息。

jstat-gcnewcapacitypid:fun对象的信息船舶概论电脑资源量。

jstat-gcoldpid:old对象的信息。

jstat-gcoldcapacitypid:old对象的信息教材习题解答占用量。

jstat-gcpermcapacitypid:perm对象的信息非盈利组织会计占用带宽量。

jstat-utilpid:统计gc信息统计。

jstat-printcompilationpid:当前VM先执行的信息。

除开以上一个参数外,还这个可以同时再加两个数字,如:jstat-printcompilation30242506是每250毫秒可以打印第二次,一共有多少可以打印6次,还这个可以另外-h3每三行总是显示看看标题。

例子:

jstat-gcutilpid100020

S0S1EOPYGC YGCT FGC FGCT GCT

47.490.0064.8246.0847.69208222058.6316822.7342081.365

0.0037.9138.5746.1347.69208232058.6916822.7342081.425这里再一次发生了四次YGGC,也就是MinorGC,工程巨大0.06s

46.690.0015.1946.1847.69208242058.7766822.7342081.510

46.690.0074.5946.1847.69208242058.7766822.7342081.510

0.0040.2919.9546.2447.69208252058.8486822.7342081.582

MajorGC总平均时间:22.734/680.334秒

MinorGC平均时间:2058.691/208230.099秒

内存 对象 空间 Java 大小

版权声明:本文内容由互联网用户自发贡献,本站不承担相关法律责任.如有侵权/违法内容,本站将立刻删除。