论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
IT评测·应用市场-qidao123.com
»
论坛
›
数据库
›
Oracle
›
深入理解JVM第二章-自动内存管理
深入理解JVM第二章-自动内存管理
立山
论坛元老
|
2022-10-27 15:59:56
|
显示全部楼层
|
阅读模式
楼主
主题
1024
|
帖子
1024
|
积分
3072
什么时候能带着理解的目标看JVM?
这个问题是我从学习Java开始,即大二上册开始,一直抱有的问题,我在网上搜索了很多次,都没有告知我明确的答案,我想现在我可以勉强给个答案,我觉得:
操作系统学习过一遍
计算机组成原理学习过一遍
有一定的汇编语言基础
Java SE有着扎实的基础
有一定的并发编程基础【因为虚拟机的设计都需要考虑高并发状态】
为什么要学习Java内存区域和内存溢出异常?
Java程序员把控制内存的权力交给了Java虚拟机,一旦出现内存泄露和溢出方面的问题,如果不了解虚拟机的内存管理机制,修正错误将会成为艰难的一项工作。
运行时数据区域有哪几类?什么时候会发生OOM?
程序计数器
定义:
程序计数器是当前线程所执行的字节码的行号指示器(程序控制流指示器),程序的分支、循环、跳转、异常处理和线程恢复等继承功能都依赖它来实现。特别的是,如果线程正在执行一个Java方法,那么它记录着虚拟机字节码指令的地址;如果执行的是本地(关键字native)方法,那么它记录着空值。
生命周期:
它是线程私有的内存,每条线程都有一个独立的程序计数器,各条线程之间互不影响,独立存储;随用户线程的启动和结束而建立和销毁。
OOM:
没有任何可能出现OOM的情况。
虚拟机栈
什么是栈帧?
每个方法被执行时,Java虚拟机都会同步创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等方法有关的信息【参考汇编语言栈的作用】。
什么是局部变量表?
局部变量表存储了方法执行过程中所有的局部变量,包括:基本数据类型、对象引用、方法返回地址(指向一条字节码指令的地址)。
定义:
每一个线程中,存储栈帧的栈就是虚拟机栈。每一个方法从被调用到执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
生命周期:
它是线程私有的内存,生命周期与线程相同。
OOM:
栈深度超出了虚拟机的最大深度,抛出StackOverflow。而假如虚拟机栈支持动态扩展,则虚拟机栈无法申请到足够的内存时,会抛出OutOfMemoryError(OOM)。
本地方法栈
和虚拟机栈大致一样,只不过本地方法栈存储的是本地方法(关键字native)的栈帧,而虚拟机栈存储的是Java方法的栈帧。
堆
定义:
几乎所有的对象实例以及数组都在堆上分配。(new关键字)
为什么说是几乎所有?
随着即时编译技术及逃逸分析技术的日渐强大,栈上分配、标量替换(应该是两种编译优化技术)已经导致对象实例有可能不在堆中而在栈中了!
什么是经典分代?
新生代和老年代,在GC回收算法中它们会成为主角哦。
在我看来,为什么堆的生命周期没有那么绝对?
大多对象实例是线程共享的(这个很明显吧,这是线程安全问题存在的根本原因),但也有少部分是线程私有的,比如:ThreadLocal它就是线程私有的堆内存区域和TLAB(下面会讲)。
从这,对自己说一句,可以明显看出的是,大多事务都不绝对,一切都是为了更好的运行而设计的,而不是为了规则本身而设计的,别太死板。生命周期由GC回收算法控制。
OOM:
堆内存不足以进行对象实例内存分配并且堆再也无法动态拓展时,会抛出OOM。
方法区
这是最难理解的内存分配区域,极其劝退,我前六次都被它劝退了,概念很绕,hh。概括来说,就是这里存储着有关类的一切信息!
永久代、元空间和方法区是什么关系?
永久代、元空间都是方法区的一种实现。在永久代被废除后,方法区的实现就采用元空间。
永久代和元空间有什么不同?
存储位置不同,永久代是堆的一部分,和新生代,老年代地址是连续的,而元空间属于本地内存;
存储内容不同,元空间存储类的元信息,而静态变量和常量池等并入堆中。相当于永久代的数据被分到了堆和元空间中。
但是,同样的,对概念别太死板,虽然现在方法区的实现是元空间,但是,堆中的那部分数据仍然是属于方法区的,也就是堆和方法区(又称非堆)其实并没有那么清晰的界限,都只不过是为了对内存进行更好的分配罢了。
定义:
它存储着虚拟机加载的类型信息、常量、静态变量和即时编译器编译后的代码缓存等长期存在的数据。
解释什么是常量池?
字符串常量池:存放字符串常量和字符串常量引用(intern存入的字符串常量引用,new方法会创建一个字符串对象同时存入一个字符串常量到池中)的内存区域,里面字符串常量不会重复。原本被归类于方法区,因为长期不会被回收;后被归类于堆,因为方法区太小,容不下这尊大佛了。
Class常量池:用于存放编译器生成的Class文件中的各种字面量(Literal)和符号引用(Symbolic References);
运行时常量池:运行时常量池可以在运行期间将符号引用解析为直接引用,由运行时常量池存储这些直接引用。也就是说,运行时常量池存储着Class常量池运行期间存入的符号引用,以及由符号引用解析出来的直接引用,还包括运行期间产生的新的常量(关于字符串String中的intern方法,如果字符串常量池中已经存在此字符串常量,不变;而如果不存在,字符串常量池存入此字符串常量的引用)
OOM:
当方法区(运行时常量池)无法满足新的内存分配需求时,会抛出OOM。
什么是直接内存?
非JVM管理的一块内存区域。
什么是NIO?
NIO是一种基于通道于缓冲区的IO方式,它可以使用Native函数库直接分配堆外内存,然后通过堆中的DirectByteBuffer对象作为这块内存的应用进行操作,显著提高了Java应用程序的性能。(偷偷占了多的内存能不显著吗?)
产生OOM的原因?
显然,直接内存超出了JVM可以管理的内存区域,因为这是它偷的内存。理想假设,本机只有2GB的运行内存,而我分配给了虚拟机2GB,但本机2GB因为NIO直接内存的存在,实际没有2GB了,那么当JVM动态拓展内存区域时,内存就不够了,就会出现OOM。
对象是如何创建的?
对象内存的分配方式有哪些?
指针碰撞:把指针向空闲空间方向挪动一段与对象大小相等的距离。
空闲列表:虚拟机维护一个列表,记录哪块内存是可用的,从列表中利用分配算法找到一块足够大的空间划分给对象实例,并更新列表,会产生外部碎片。
具体选择哪种方式取决于虚拟机的垃圾回收策略,这种两种内存方式参考了操作系统的内存分配策略。
内存分配的并发问题如何解决?
同步处理:利用CAS算法(Compare And Swap)配上失败重试机制,保证分配内存操作的原子性。
TLAB:Thread Local Allocation Buffer,每个线程先在线程的本地缓冲区中分配,本地缓存区用完了再利用同步处理分配线程的本地缓存区。
可以使用-XX:+/-UseTLAB来配置TLAB。
对象实例在堆中的内存分布布局?
对象头、实例数据和对齐填充。
对象头存储着什么信息?
一部分是用于存储对象自身的运行时数据,如哈希码、GC分代年龄、锁状态标志、线程持有的锁(客户端锁定)、偏向线程ID、偏向时间戳等。
另一部分用于存储类型指针,即对象指向它的类型元数据的指针,通过这个来确定对象是哪个类的实例。(反射会用到)如果是数组,还会存储数组的长度,因为一般的对象实例通过元数据信息已经可以确定大小,而数组不行。
实例数据存储着什么信息?
程序代码里所定义的各种类型的字段内容。
为什么要对齐填充?
就和计网IP数据报以及计组里学的一样,数据最好封装成字节的整数倍,方便CPU读取。
对象如何进行访问定位?
使用句柄
如果使用句柄访问,在java堆中将划分出一块内存来作为句柄池。reference中存储的就是对象的句柄地址,而句柄中包含对象实例数据与类型数据具体地址信息。
直接访问
使用直接访问,在java堆中对象的内存布局就必须考虑如何放置访问类型数据的相关信息。reference中直接存储对象地址即可。
句柄访问和直接访问的优缺点
句柄访问在引用和具体数据之间增加了一层转换关系,这层转换关系使得对象在被移动的时候(如垃圾回收)只需要改变转换关系,即改变句柄池中的引用指向即可。而引用本身不需要被修改。使用直接访问最大的好处就是快,因为相对于句柄访问减少了一次指针定位的时间。由于java是面向对象语言,对象访问非常频繁,因此这种访问开销积少成多也非常可可观。hotspot虚拟机使用的就是直接访问方式。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
立山
论坛元老
这个人很懒什么都没写!
楼主热帖
IoTOS-v1.5.3 新增 智能诊断&会话记录 ...
【学习笔记】WPF-01:前言
基于SqlSugar的开发框架循序渐进介绍( ...
网络安全-技术与实践 书本习题练习 ...
IO流的使用
CentOS7 单机版使用kubeadm安装K8S ...
Python中可以用三种方法判断文件是否存 ...
开源直播课丨大数据集成框架ChunJun类 ...
WEB安全基础入门—身份验证漏洞 ...
解读数仓常用模糊查询的优化方法 ...
标签云
AI
运维
CIO
存储
服务器
浏览过的版块
移动端开发
linux
容器及微服务
DevOps与敏捷开发
Mysql
SQL-Server
数据仓库与分析
运维.售后
.Net
快速回复
返回顶部
返回列表