首页 >行情 > > 正文

JVM-内存结构篇笔记-全球热讯

腾讯云 2023-02-17 05:59:16

本文原创,内容结合视频 黑马程序员JVM完整教程,Java虚拟机快速入门,全程干货不拖沓_哔哩哔哩_bilibili 和 周志明 - 《深入理解Java虚拟机》而作,同步发于个人博客:JVM-内存结构篇 - Karos (wzl1.top) 与 腾讯云开发者社区:JVM-内存结构篇笔记 - 腾讯云开发者社区-腾讯云 (tencent.com),部分图片来源已添加链接

JVM

Java 内存区域与内存溢出异常

运行时数据区域

image-20230122220140540

程序计数器(PCR)

==记录下一条指令的地址==

PCR是一个较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器(==不会存在内存溢出==)。


(相关资料图)

在JVM的概念模型中,字节码解释器工作时就是通过改变PCR的值来选取下一条需要执行的字节码指令,是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基本功能都依赖这个计数器来完成。

程序控制流:控制流是指按一定的顺序排列程序元素来决定程序执行的顺序

由于JVM的多线程是通过线程轮流替换、分配处理器执行时间的方式(抢占式调度方式)来实现,因此在任意一个确定时刻,一个处理器或一个内核都只会执行一条线程中的指令。

Java的JVM虚拟机线程调度和进程调度方式 - 简书 (jianshu.com)

为了保证线程切换后能回到正确的执行位置,所以每条线程都要有一条独立的程序计数器,互不影响、独立存储,称这块区域为线程的私有内存。

如果线程正在执行的是一个Java方法,那么PCR记录的是正在执行的虚拟机字节码指令的字节地址

如果是个本地方法,则为空

(78条消息) Java本地方法调用外星喵的博客-CSDN博客本地方法的调用

Java虚拟机栈

==线程运行时需要的内存空间==

生命周期与线程相同,描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态连接、方法出口等信息。

垃圾回收是否设计栈内存? 不涉及,只涉及堆内存占内存分配越大越好吗?-Xss1m #通过-Xss来设置栈内存,Linux/x64、macOs、OracleSolaris/x64 默认为1024KB=1m,Windows会根据虚拟内存影响栈的大小唯一的好处就是增大方法的递归调用,以及间接调用,明显的坏处就是减少线程数。方法内的局部变量是否线程安全? 由于Java虚拟机栈线程隔离,而一个方法的局部变量存放于栈帧中,所以线程安全,如果是共享变量(静态变量),那么线程不安全

局部变量表

存放编译器可知的各种JVM基本数类型、对象引用和returnAddress类型(指向了一条字节码指令的地址),存储空间以局部变量槽(Slot)表示,long和double占2个slot。

表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配的局部空间大小完全确定,在方法运行期间不会改变局部变量表的大小(slot的数量)

栈内存溢出

栈帧过多导致栈内存溢出递归调用循环依赖

解决方法:@JsonIgnoreSpring 通过三级缓存解决循环依赖

栈帧过大导致栈内存溢出

线程运行诊断

案例1: cpu占用过多

定位:

用top命令定位那个进程对cpu的占用过高ps H -eo pid,%cpu | grep 进程id

#用ps命令进一步定位是哪一个线程引起的

jstack 进程id

jstack中:tid: java内的线程idnid: 操作系统级别线程的线程idprio: java内定义的线程的优先级os_prio:操作系统级别的优先级操作系统中:pid: 进程ID。lwp: 线程ID。在用户态的命令(比如ps)中常用的显示方式。tid: 线程ID,等于lwp。tid在系统提供的接口函数中更常用,比如syscall(SYS_gettid)和syscall(__NR_gettid)。tgid: 线程组ID,也就是线程组leader的进程ID,等于pid。------分割线------pgid: 进程组ID,也就是进程组leader的进程ID。pthread id: pthread库提供的ID,生效范围不在系统级别,可以忽略。sid: session ID for the session leader。tpgid: tty process group ID for the process group leader。

windows: tasklist无结果(线程死锁)jstack 进程id
![image-20230214172749657](http://gd.7n.cdn.wzl1.top/typora/img/image-20230214172749657.png)

本地方法栈

本地方法:由C/C++等与操作系统打交道的语言编写

与VM Stack类似,区别在于服务对象不同,NMS为JVM用到的本地方法服务

Java堆

Java Heap是虚拟机所管理的内存中最大的一块,是被所有线程共享的一块内存区域,在虚拟机启动时创建。

唯一目的:存放对象实例

从分配内存的角度看,所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区(TLAB),提升对象分配时的效率。

Java Heap在物理上可以不连续,但在逻辑上应该连续

可以通过设置参数-Xmx和-Xms设定Java Heap是固定大小还是可扩展

通过new关键字,创建对象都会使用堆内存线程共享,堆中的 对象都需要考虑线程安全问题有垃圾回收机制

堆内存溢出

成次幂

堆内存诊断

工具>>

image-20230214184717834
示例:

JMAP

jmap -heap PID

左:堆配置右:堆内存占用情况

JConsole

image-20230214205736847

JvirsualVm

image-20230215031704078

具有堆转储功能(堆Dump),截取快照

方法区

==所有Java虚拟机线程共享的区域==

存储和类相关的信息、成员方法、构造器方法、特殊方法

创建时期:虚拟机被启动时,逻辑上是堆的一部分,但事实不一定。

方法区的实现:永久代(hotspotJDK1.8以前)、元空间(操作系统内存)

image-20230215045133801

如果申请内存时发现内存不住,也会发出outofMemoryError异常

线程共享的内存区域,用于存储已被虚拟机加载的类型模型、final、static、即时编译器编译后的代码缓存

内存溢出

image-20230215050458867

元空间默认情况下使用系统内存,无上限

#设定原空间内存溢出-XX:MaxMetaspaceSize=XXX#设置永久代内存溢出-XX:MaxPermSize=XXX
image-20230215052109506
image-20230215052551991

场景:

Cglib

SpringMyBatis

常量池

Java堆类进行编译时,会产生二进制字节码,包含类基本信息、常量池、类方法定义(包含了虚拟机指令)

image-20230215055456838
通过javap指令对.class文件进行反编译

类的基本信息

image-20230215055435608

类的方法定义

无参构造
main方法
image-20230215055823167
常量池
image-20230215063424268

运行时常量池(Runtime Constant Pool)

从上面可以看出,常量池其实就是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法铭、参数类型、字面量等信息

RCP是方法区的一部分,常量池是*.class文件中的,当该类被加载,它的常量池信息就会背放入运行是常量池,并把里面的符号变为真实地址。

Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息时常量池表(Constant Pool Table),CPT用于存放你编译器生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

RCP相对于Class文件常量池的另外一个重要特征:动态性

Java并不要求常量一定要在编译器才能产生,也就是说并非预置入Class文件中的常量池的内容才能进入方法区运行常量池,运行期间也可以将新的常量放入池中,比如String::inter

:tada:String::inter()

image-20230122235442146

StringTable

image-20230215161421366

使用变量相加,由于是变量,所以不会在编译期间优化

特性

常量池中的字符串仅是符号,第一次使用到时才变为对象利用串池机制,避免重复创建字符串对象字符串变量拼接的原理是StringBuilder(1.8).append字符串常量拼接的原理是编译器优化可以使用intern方法,主动将串池中还没有的字符串对象放入串池1.8 将这个字符串对象尝试放入串池,如果有则不会放入,如果没有则会放入串池,并返回
image-20230215163719209
>true
>
>true
![image-20230215163710427](http://gd.7n.cdn.wzl1.top/typora/img/image-20230215163710427.png)
1.6 将这个字符串对象尝试放入串池,如果有则不会放入,如果没有则会把这个对象赋值一份,放入串池,会把串池中的对象返回
image-20230215180145104

面试题

image-20230215071801534

位置

1.8之前,放在方法去永久代中,而1.7 1.8之后放在堆里面

image-20230215181821229

垃圾回收

image-20230215184329180

异常抛出,默认启用此选项,如果超过98%的时间用于垃圾收集,则并行GC将抛出一个outofMemoryError

并且不到2%的堆被恢复。当堆很小时,这个特性可以用来防止应用程序长时间运行,而不会有什么进展。若要禁用此选项,

指定选项-xx:-UseGCOverheadLimit

-XX:+PrintStringTavleStatistics #打印字符串表的统计信息#打印垃圾回收的详细信息-XX:+PrintGcDetails-vaerbase:gc
image-20230215201809922
image-20230215201904326

类名、方法名也是以字符串常量的形式存储在JVM中,当内存空间不足,内存分配失败时会进行垃圾回收

image-20230216024912772

调优

修改哈希桶个数,改变存储、查询时间

-XX:StringTableSize=xxxx #设置StringTable哈希表 桶的个数

考虑将字符串对象是否入池

直接内存

直接内存(Direct Memory)并不是虚拟机运行时数据区的一部分,也不是《JVM》规范中定义的内存区域。

在JDK 1.4中新加入了NIO类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用操作,避免了在Java Heap和Native Heap中来回复制数据

直接内存属于系统内存

常见于NIO操作、用于数据缓冲区分配回收成本高,但读写性能强不受JVM内存回收管理

传统IO

img

直接内存

ByteBuffer.allocateDirect(_1Mb); //分配直接内存

image-20230216040351823

直接内存溢出

image-20230216040900894

直接内存释放

image-20230216043702897
image-20230216043657291

Cleaner (虚引用类型)当前对象被回收时会执行一个回调方法

image-20230216052204620

阿里面试: 说说强引用、软引用、弱引用、虚引用吧 - 腾讯云开发者社区-腾讯云 (tencent.com)强:打死都不删除软:容量不够了再删弱:有gc就删虚:随时都可以被删(设置虚引用的唯一目的,就是在这个对象被回收器回收的时候收到一个系统通知或者后续添加进一步的处理

img
image-20230216052441677
image-20230216052423752

clean()方法在后台的RefenceHandler线程中检测虚引用对象,一旦虚引用对象关联的实际对象被回收掉后,就会执行clean方法

分配和回收原理:
image-20230216053629422

禁用显示回收对直接内存的影响

-XX:+DisableExplicitGC #显示的,禁用System.gc();

被禁用后对直接内存使用回调影响:无法手动进行垃圾回收,导致长时间占用直接内存

解决:

手动使用unsafe.fereeMemory

HotSpot虚拟机对象揭秘

对象的创建

当虚拟机遇见一条字节码new指令,首先会检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用的类是否已被加载、解析、初始化过。如果没有,那必须先执行相应的类加载过程。

HotSpotCreateObject

HotSpot解释器代码片段

// 确保常量池中存放的是已解释的类  if (!constants->tag_at(index).is_unresolved_klass()) {    // 断言确保是klassOop和instanceKlassOop(这部分下一节介绍)    oop entry = (klassOop) *constants->obj_at_addr(index);    assert(entry->is_klass(), "Should be resolved klass");    klassOop k_entry = (klassOop) entry;    assert(k_entry->klass_part()->oop_is_instance(), "Should be instanceKlass");    instanceKlass* ik = (instanceKlass*) k_entry->klass_part();    // 确保对象所属类型已经经过初始化阶段    if ( ik->is_initialized() && ik->can_be_fastpath_allocated() ) {      // 取对象长度      size_t obj_size = ik->size_helper();      oop result = NULL;      // 记录是否需要将对象所有字段置零值      bool need_zero = !ZeroTLAB;      // 是否在TLAB中分配对象      if (UseTLAB) {        result = (oop) THREAD->tlab().allocate(obj_size);      }      if (result == NULL) {        need_zero = true;        // 直接在eden中分配对象  retry:        HeapWord* compare_to = *Universe::heap()->top_addr();        HeapWord* new_top = compare_to + obj_size;        // cmpxchg是x86中的CAS指令,这里是一个C++方法,通过CAS方式分配空间,并发失败的话,转到retry中重试直至成功分配为止        if (new_top <= *Universe::heap()->end_addr()) {          if (Atomic::cmpxchg_ptr(new_top, Universe::heap()->top_addr(), compare_to) != compare_to) {            goto retry;          }          result = (oop) compare_to;        }      }      if (result != NULL) {        // 如果需要,为对象初始化零值        if (need_zero ) {          HeapWord* to_zero = (HeapWord*) result + sizeof(oopDesc) / oopSize;          obj_size -= sizeof(oopDesc) / oopSize;          if (obj_size > 0 ) {            memset(to_zero, 0, obj_size * HeapWordSize);          }        }        // 根据是否启用偏向锁,设置对象头信息        if (UseBiasedLocking) {          result->set_mark(ik->prototype_header());        } else {          result->set_mark(markOopDesc::prototype());        }        result->set_klass_gap(0);        result->set_klass(k_entry);        // 将对象引用入栈,继续执行下一条指令        SET_STACK_OBJECT(result, 0);        UPDATE_PC_AND_TOS_AND_CONTINUE(3, 1);      }    }  }  
上一篇: 下一篇:
x
推荐阅读

JVM-内存结构篇笔记-全球热讯

2023-02-17

02月17日00时广东东莞疫情数据 阳了以后为什么会腰疼?应该怎么办? 全球热点评

2023-02-17

天天亮点!量子理论

2023-02-16

珠海香洲长途汽车站网上购票去哪里?|环球播资讯

2023-02-16

当前热讯:杭州应届大学生租房补贴常见问题解答(持续更新)

2023-02-16

江山欧派(603208)2月16日主力资金净买入25.10万元

2023-02-16

长沙玉湖公园有什么花?

2023-02-16

医保断缴会有什么影响 医保断交可以补交吗

2023-02-16

欧文为什么叫UncleDrew-每日热讯

2023-02-16

世界球精选!ipad qq音乐二维码登录_ipad qq闪退

2023-02-16

同居关系_关于同居关系的介绍_每日聚焦

2023-02-16

环球即时看!购买车辆保险需要注意什么_购买车保险注意事项是什么?

2023-02-16

观音灵签15签解签是什么意思_环球今热点

2023-02-16

分手后的日志_分手后的伤感长篇日志_重点聚焦

2023-02-16

全球速读:恶参兽_关于恶参兽的介绍

2023-02-16

全国爱耳日是几月几日,2020年全国爱耳日是几月几日

2023-02-15

沟槽式连接和卡箍式连接的区别_沟槽式连接

2023-02-15

非同质化代币是什么意思

2023-02-15

全球热点评!2021立秋是几月几号 2021立秋的时间介绍

2023-02-15

每日视讯:交通银行华润苏果信用卡有年费吗?

2023-02-15

乘机的近义词 乘机的意思

2023-02-15

每日信息:低风险和无风险一样吗

2023-02-15

高伟达董秘回复:快读科技正在与相关各方协调,争取早日完成ICP牌照的续期或重新申请

2023-02-15

染色岩石的技术 热门看点

2023-02-15

全球快播:椰树集团直播被掐断背后有3个细节 都是擦边球惹的祸

2023-02-15

如何在一块石板上钻孔

2023-02-15

今日热文:新华联 :下属子公司涉一笔5.92亿元金融借款合同纠纷案件

2023-02-15

激励孩子积极向上的良言妙语

2023-02-15

被逼到盈利绝境的中视频-全球快资讯

2023-02-15

奇瑞五座suv_奇瑞五娃敞篷多少钱?

2023-02-15

中国十大名校排名简介 天天动态

2023-02-15

全球视点!前列腺炎能吃三金片吗?_前列腺炎可以吃三金片吗

2023-02-15

豆芽的生长过程日记400字 环球快播

2023-02-15

全球观速讯丨点燃城市“烟火气” 随机舞蹈城市快闪空降新百广场

2023-02-14

一盆长春花阅读理解题及答案|环球消息

2023-02-14

表达爱意的日子|情叙长沙,大屏传递 今日热议

2023-02-14

江西袁州:举办专场推介会 助力退役军人精准就业_讯息

2023-02-14

安全工程师考试时间及科目

2023-02-14

当前信息:前脚投进三分,后脚就被换下,火箭打算就这样培养内线新星?

2023-02-14

全球快看:材料暂估入库会计分录

2023-02-14

世界信息:中级会计职称《财务管理》考点:企业的社会责任

2023-02-14

焦点快看:新车品鉴:奇瑞蚂蚁公布预售价 区间为16-17万元

2023-02-14

2022年我国充电桩数量同比增长近100% 每日热文

2023-02-14

嘉实基金滕抒含:ChatGPT应用广泛 软件板块真正受益

2023-02-14

爱镜眼镜网_诚镜眼镜网

2023-02-14

情人节送什么礼物合适

2023-02-14

环球最新:体温计的刻度一般在多少之间

2023-02-14

索伦_说一说索伦的简介 全球关注

2023-02-14

如懿真的斗不过魏嬿婉

2023-02-13

【ES三周年】一份初学者的Elasticsearch入门笔记 环球快播报

2023-02-13

天天微头条丨2023冬季|到青岛去看海,还有这6家新开的咖啡店让人留恋往返

2023-02-13

每日观察!肇事逃逸车保险管吗

2023-02-13

日是什么意思网络用语|热点聚焦

2023-02-13

赞!中国第13批赴南苏丹(瓦乌)维和医疗分队通过联合国装备核查

2023-02-13

中汽协:1月汽车企业出口30.1万辆 同比增长30.1%

2023-02-13

智库报告:多地未雨绸缪缓解春节后“用工荒” 焦点快看

2023-02-13

腿有静脉曲张怎么调理最有效_腿有静脉曲张怎么调理

2023-02-13

世界热议:你喝的肥宅快乐水,各科医生都显然不淡定了

2023-02-12

有声听书在线收听_有声听书

2023-02-12

看点:特斯拉引发,丰田跟进,比亚迪加码,汽车降价才是硬道理

2023-02-12

送领导礼物|每日看点

2023-02-12

【全球热闻】一图读懂丨庆阳市银政企对接活动

2023-02-11

吉林好人|张录燕:透析患者“生命线”的坚守者

2023-02-11

白毫银针泡出来的颜色发红正常吗 白毫银针泡多久出汤

2023-02-11

全球关注:中足联筹备组:努力推出中超足球彩票

2023-02-11

埃及达曼胡尔市一楼房倒塌 至少6死23伤_世界热资讯

2023-02-11

六级满分多少分_六级满分

2023-02-11

做黑脸娃娃痛不痛 做完黑脸娃娃之后的注意事项

2023-02-11

多少岁以下算儿科_多少岁以下算儿童 全球新视野

2023-02-11

每日焦点!hp540怎么设置u盘启动_hp540驱动

2023-02-11

勇的部首和结构_勇的部首

2023-02-10

环球播报:步科股份业绩快报:2022年净利润同比增长22%

2023-02-10

关于软文的来源、写作技巧、资源的收集

2023-02-10

中考考差了怎么办

2023-02-10

中餐餐厅简介范文大全(热门49篇)

2023-02-10

最全的《离歌》小说句子下载 离歌小说经典语录-环球今日报

2023-02-10

上海市场监督管理局:过度包装!这9批次商品包装物减量抽查不合格 环球热文

2023-02-10

平安夜送礼物留言

2023-02-10

ST三圣董秘回复:如大股东资金占用导致公司产生实际损失,公司将通过法律手段进行追偿_全球快播

2023-02-10

鸡和梨成语_人财梨鸡猜一个成语_环球热推荐

2023-02-10

【天天快播报】弘业期货:夜盘振幅不大,铁矿石短期内维持偏强震荡

2023-02-10

圣诞节准备什么礼物给女生 天天看点

2023-02-10

浙江旅游必去十大景点|今日热文

2023-02-10

房子施工知识:地板表面的漆膜剥落是何原因?

2023-02-10

全球看热讯:在劫难逃歌词_关于在劫难逃歌词的介绍

2023-02-10

女生右下腹部疼痛怎么回事_女性右下腹部疼痛怎么回事

2023-02-10

焦点热讯:王姬的老公高峰是演员吗_演员王姬老公是谁 揭王姬和高峰的坎坷婚姻经历

2023-02-09

送男客户什么礼物好,最重要的是有创意-环球看热讯

2023-02-09

环球讯息:北京公积金租金补贴虚假申报或骗取补贴有什么后果?

2023-02-09

环球快资讯:秦阳明解析2020年生肖狗桃花运,感情运势节节攀升,爱情开花结果

2023-02-09

联盟新兵:2022年日产Qashqai&RogueSport 今日关注

2023-02-09

朝阳县气象局发布道路结冰黄色预警【Ⅲ级/较重】|环球观热点

2023-02-09

永恒之眼入口在哪_永恒之眼入口详情 看点

2023-02-09

新闻追踪:加梯工程再度停滞 施工队又无踪影

2023-02-09

动态:算力概念持续发酵 力昂技术涨停

2023-02-09

爱奇艺会员怎么取消自动续费 爱奇艺会员取消自动续费的方法 今日关注

2023-02-09

【脑吧装机服务】装机实录素材招聘×,粉丝装机福利√

2023-02-09

人妻设计“电竞厕所”送给丈夫,网友:我能拉一天

2023-02-09

南京小支烟多少钱一包2022新 南京小支烟香烟价格排行榜 全球新动态

2023-02-09

苹果6发送短信失败怎么回事_iPhone6一发短信就死机如何解决

2023-02-09