您现在的位置: 首页 趋势 > > 正文
热点聚焦:JVM-内存结构篇笔记
发布时间:2023-02-16 08:57:30 来源:腾讯云

本文原创,内容结合视频 黑马程序员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);      }    }  }  

标签: Java 编程算法

热点聚焦:JVM-内存结构篇笔记

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

全球新动态:阿森纳走下神坛只用三场 联赛对阵曼城遭耻辱11连败

在今天凌晨结束的英超联赛中,卫冕冠军曼城在客场3-1战胜此前排名榜首的阿森纳,成功超越对手顺利登顶。...

nokia 5600_nokia 5800i-世界微资讯

1、以前推出过太多的诺基亚滑盖手机。今天,我破例向您介绍一款诺基亚直板手机。说起直板手机,恐怕没有...

牧姓起名大全,姓牧起名 天天新动态

牧闻妍牧绪颖牧素玲牧婧颖牧湘梅牧咏琴牧媛熙牧红琼牧腊梅牧咏红牧美丽牧书婵牧益丽牧雨琳牧菊英牧翠英...

【世界热闻】女士自动挡省油小型车_适合女生开的车10万以内

1、广汽本田的新飞度。2、外表没的说价钱在8 68-13万之间,你可以选择10万以下款的,很适合女孩子开很时尚的重

属羊人的婚姻与命运如何

属羊人的婚姻是比较稳定的,彼此双方对婚姻都是无比的忠诚。属羊的人对于自己的婚姻是非常重视的,他们...

1月存续私募规模超20万亿元千余家私募基金管理人遭注销 环球动态

2月15日晚,中国证券投资基金业协会(下称“中基协”或“协会”)发布了私募基金管理人登记及产品备案月报...

笔记本电脑报价网_笔记本电脑报价单_笔记本报价单

一.笔记本报价单:联想的G450A-TFO(H)T4300奔腾双核2G内存250G硬盘512M独显DVD刻录无线摄像头11英寸价钱大概在3700到

焦点资讯:建设银行卡输错密码三次多长时间解锁

建设银行卡输错密码三次,帐号将被锁定,24小时自动解锁。如果24小时不能自动解锁,持卡人凭本人有效身...

全球快报:上证指数的点数是代表什么意思

上证指数的点数是股价指数,是通过统计上的指数法编制的,用来反映股票市场的整体价格或某一类股票价格...

天天最资讯丨今日兰陵皇妃结局番外_兰陵皇妃结局

1、高长恭死后四年,宇文邕出师灭齐统一的周和大齐。然而宇文勇始终没有找到袁清锁的下落。但是,袁清锁...

热点聚焦:交强险买了多久生效

购买交强险后,一般从第二天零时开始生效。交强险具体的生效时间,会在保单上有详细说明。另外,如果是...

全球热点评!清明时节雨纷纷是哪首古诗 清明时节雨纷纷原文及译文

1、“清明时节雨纷纷”出自唐朝杜牧的《清明》。2、《清明》唐:杜牧清明时节雨纷纷,路上行人欲断魂。...

【聚看点】不能任由非学科类培训再走老路

新闻背景:进入新学期,不少家长又开始考虑给孩子报班,五花八门的非学科类校外培训迅速升温。日前,教...

2023南昌九龙湖社区卫生服务中心重点人群免费体检通知

➤南昌九龙湖社区卫生服务中心国家基本公共卫生服务项目免费体检通知:尊敬的九龙湖居民:您们好!为切...

什么是销售

要和顾客交朋友吗?这是一个销售中常见的问题,那么要怎么做呢?如何做?需要去做吗?下面小编从什么是销售...

葛洲坝宜城水泥公司成功入选国家级绿色工厂

葛洲坝宜城水泥公司成功入选国家级绿色工厂

金汇得手:黄金过山车行情 今日主多辅空操作

美元指数昨天走势还是震荡为主,今日关注102 5-103 6区间。黄金昨天再次走出过山车行情,日线收十字星...

如何制作纸质二十面体-短讯

你需要的东西厚纸剪刀整拳细绳或麻花领带二十面体是一个有20个边的形状。用纸制作一个20边形的二十面体...

如何做到讲规矩有纪律学习心得体会8篇

守纪律讲规矩,才能增强党的凝聚力、创造力和战斗力,保障党和国家的事业健康发展,下面是学习啦为大家...

圆舞曲的起源是什么_世界热闻

华尔滋又称华尔兹(Waltz),又称圆舞,一种自娱舞蹈形式。华尔兹舞曲,即圆舞曲也常被称为华尔兹。那么,...

全球动态:中国足坛大地震,李铁案背后大boss终现出原形,名记:扫黑大结局

中国足坛大地震,李铁案背后大boss终现出原形,名记:扫黑大结局,扫黑,大鱼,李铁案,大地震,中国足球,中...

传统旅行社盈利模式_旅行社的盈利模式

1、去百度文库,查看完整内容>内容来自用户:中国学术期刊网旅行社盈利模式创新摘要:伴随着旅游行业竞争...

天天快报!2017lols7通用符文有哪些

2017英雄联盟LOL符文系统改版,全部的符文变成了基石符文,很多玩家都不知道全英雄符文。那么2017LOL符...

广东多地一夜降温10℃ 全省89个寒冷预警信号生效

中新社广州2月14日电(记者王坚)冷空气于14日5时全面影响广东,该省气温骤降,多地气温较13日下降8℃至11...

散文随笔:自己的爱情-速看料

环球新资讯:李逵还是李鬼,五菱首款电动SUV,好似迷你版坦克300

城管没收男孩作业桌,官方:已责令道歉_快讯

企业欠税可以分期还清吗

雅思作文:娱乐活动

简单昵称阳光 简洁温暖阳光的网名大合集

天风证券:AIGC技术、应用和产业生态迎来发展快车道,关注相关场景应用拓展

拜仁官网介绍巴黎:几乎每个位置都是世界级,胜场数巴黎略优

中国已成立国家新冠病毒中心 更好地应对疫情-百事通

超低能耗建筑拟最高奖600万

华为手环B6配置参数_华为手环B6最新性能参数 热门看点

李戈个人资料_李戈介绍

子婴是怎么死的|天天新视野

每日报道:提质增效!鄂尔多斯市政府办公室跑出办文办会“加速度”

电脑上回车键是哪个键

实现总产值150亿 !九牧高端定制产业园正式投产-天天快资讯

CBA最新消息!男篮热身赛曝光,郭士强退出国家队,大鸟不务正业

英国政党_关于英国政党的基本详情介绍|当前视点

我可以在 14 Poulan 电锯上放多大的钢筋?-天天短讯

秋景诗意句子 秋景诗句唯美-环球视点

环球快播:男人喜欢什么生日礼物

焦点信息:现在办理离婚需要户口本吗

父母爱情电视剧全集_十二岁生日父母发言稿

世界信息:吸烟酗酒等都是其诱发因素胃糜烂运城众泰医院这儿治准确吗

世界快资讯:有望今日首次合体!东契奇晒出多张与欧文训练合照!

“我要求不高,只要600万!”北京“钉子户”占道8年,结局如何 环球热点

婚外情送男人礼物排行榜

世界快看点丨狠的组词是什么_狠出色的组词

2022年中国涤纶长丝行业竞争格局及重点企业分析

全球球精选!实现近二十年来的期盼 四川雅安今年要全力拼进“千亿俱乐部”

环球热头条丨缉毒犬有接班“鼠”了!中国首批“缉毒松鼠”即将上岗

金博股份(688598)2月10日主力资金净卖出83.97万元

天天观速讯丨小伙给女友过生日送什么礼物

南京化妆品批发网怎么样?南京有哪些化妆品批发市场?-世界热消息

阴雨+冷空气“控场”,南京未来三天阴雨仍是主角 焦点简讯

天天即时:珈伟新能退场锂电 行业中小企业面临危机?

renecaovilla官网_rene caovilla 每日报道

【环球快播报】2月13日至15日昭通北部有小雪或雨夹雪

怎么把qlv格式转成mp4,这个方法我想介绍给你-世界快看点

热推荐:女生节送什么手机好

【环球播资讯】今日白银价格多少钱一克(2023年2月10日)

观察:新土味情话2020_新土味情话

请问被卖家恶意差评了怎么办 每日短讯

万代的2022:收入520亿元,龙珠和高达贡献136亿

环球热头条丨如何判断肉桂的好坏 挑选肉桂的技巧

环球热点评!梦幻新诛仙妖王黑水玄蛇怎么过

实施9项计划推进重点群体创业 环球快播报

高曙光妻儿探班,他穿棉服小16岁娇妻穿短袖,4岁儿子似他翻版

环球信息:动车车次怎么看

【全球独家】炖鸡放什么料好吃_炖鸡汤放什么调料

x 广告
x 广告

Copyright ©  2015-2022 全球自然网版权所有  备案号:豫ICP备20009784号-11   联系邮箱:85 18 07 48 3@qq.com