jvm概述

021f020383b44139ba5b420dad2f8ff6.jpg

 

1、JVM体系结构

 

 

2、JVM运行时数据区

 

 

3、JVM内存模型

JVM运行时内存 = 共享内存区 + 线程内存区

 

 

3.1、共享内存区

共享内存区 = 持久带(方法区 + 其他)+ 堆(Old Space + Young Space(den + S0 + S1))

 

持久代:

JVM用持久带(Permanent Space)实现方法区,主要存放所有已加载的类信息,方法信息,常量池等等。可通过-XX:PermSize和-XX:MaxPermSize来指定持久带初始化值和最大值。Permanent Space并不等同于方法区,只不过是Hotspot JVM用Permanent Space来实现方法区而已,有些虚拟机没有Permanent Space而用其他机制来实现方法区。

堆(heap):

主要用来存放类的对象实例信息(包括new操作实例化的对象和定义的数组)。

堆分为Old Space(又名,Tenured Generation)和Young Space。Old Space主要存放应用程序中生命周期长的存活对象;Eden(伊甸园)主要存放新生的对象;S0和S1是两个大小相同的内存区域,主要存放每次垃圾回收后Eden存活的对象,作为对象从Eden过渡到Old Space的缓冲地带(S是指英文单词Survivor Space)。堆之所以要划分区间,是为了方便对象创建和垃圾回收.

 

3.2、线程内存区

 

线程内存区(JVM栈):

线程内存区=单个线程内存+单个线程内存+.......

单个线程内存=PC Regster+JVM栈+本地方法栈

JVM栈=栈帧+栈帧+.....

栈帧=局域变量区+操作数区+帧数据区

在Java中,一个线程会对应一个JVM栈(JVM Stack),JVM栈里记录了线程的运行状态。JVM栈以栈帧为单位组成,一个栈帧代表一个方法调用。栈帧由三部分组成:局部变量区、操作数栈、帧数据区。

线程在栈区,不能共享数据,只能通过复制共享区的数据作为一块缓存,所有多线程写会有bug,voliate使得取到的数据不做缓存,是实时更新的。关键字 volatile 是轻量级的同步机制。

Volatile 变量对于all线程的可见性,指当一条线程修改了这个变量的值,新值对于其他 线程来说是可见的、立即得知的。 Volatile 变量在多线程下不一定安全,因为他只有可见性、有序性,但是没有原子性。

 

二、JVM内存空间管理

JVM把内存划分了如下几个区域:

 

共享内存区 = 持久带(方法区 + 其他)+ 堆(Old Space + Young Space(den + S0 + S1));

Java 内存模型和线程:

每个线程都有一个工作内存,线程只可以修改自己工作内存中的数据,然后再同步回主内存,主内存由多个内存共享。

 

2.1 方法区(共享内存区的持久带)

方法区 (又称为持久代):要加载的类的信息(名称、修饰符等)、类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息。方法区域也是全局共享的,当开发人员调用类对象中的getName、isInterface等方法来获取信息时,这些数据都来源于方法区。

在一定条件下它也会被GC,当方法区域要使用的内存超过其允许的大小时,会抛出OutOfMemory:PermGen Space异常。的错误信息。在Sun JDK中这块区域对应Permanet Generation,,默认最小值为16MB,最大值为64MB,可通过-XX:PermSize及-XX:MaxPermSize来指定最小值和最大值。

在Hotspot虚拟机中,这块区域对应的是Permanent Generation(持久代),一般的,方法区上执行的垃圾收集是很少的,因此方法区又被称为持久代的原因之一,但这也不代表着在方法区上完全没有垃圾收集,其上的垃圾收集主要是针对常量池的内存回收和对已加载类的卸载。在方法区上进行垃圾收集,条件苛刻而且相当困难,关于其回后面再介绍。

运行时常量池(Runtime Constant Pool)是方法区的一部分,用于存储编译期就生成的字面常量、符号引用、翻译出来的直接引用(符号引用就是编码是用字符串表示某个变量、接口的位置,直接引用就是根据符号引用翻译出来的地址,将在类链接阶段完成翻译);

运行时常量池除了存储编译期常量外,也可以存储在运行时间产生的常量,比如String类的intern()方法,作用是String维护了一个常量池,如果调用的字符“abc”已经在常量池中,则返回池中的字符串地址,否则,新建一个常量加入池中,并返回地址。JVM方法区的相关参数,最小值:--XX:PermSize;最大值 --XX:MaxPermSize。

 

2.2 堆区(堆区由所有线程共享)

堆用于存储对象实例及数组值,可以认为Java中所有通过new创建的对象的内存都在此分配,堆区由所有线程共享。Heap中对象所占用的内存由GC进行回收,在32位操作系统上最大为2GB,在64位操作系统上则没有限制,其大小可通过-Xms和-Xmx来控制,-Xms为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1GB;-Xmx为JVM可申请的最大Heap内存,默认为物理内存的1/4但小于1GB,默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过-XX:MinHeapFreeRatio=来指定这个比例;当空余堆内存大于70%时,JVM会减小Heap的大小到-Xms指定的大小,可通过-XX:MaxHeapFreeRatio=来指定这个比例,对于运行系统而言,为避免在运行时频繁调整Heap 的大小,通常将-Xms和-Xmx的值设成一样。

堆区是理解JavaGC机制最重要的区域。在JVM所管理的内存中,堆区是最大的一块,堆区也是JavaGC机制所管理的主要内存区域,堆区由所有线程共享,在虚拟机启动时创建。堆区用来存储对象实例及数组值,可以认为java中所有通过new创建的对象都在此分配。

 

2.3 本地方法栈(Native Method Stack)

本地方法栈用于支持native方法的执行,存储了每个native方法调用的状态。本地方法栈和虚拟机方法栈运行机制一致,它们唯一的区别就是,虚拟机栈是执行Java方法的,而本地方法栈是用来执行native方法的,在很多虚拟机中(如Sun的JDK默认的HotSpot虚拟机),会将本地方法栈与虚拟机栈放在一起使用。

 

2.4 虚拟机栈(JVM Stack)(线程私有)

JVM方法栈:为线程私有,其在内存分配上非常高效。当方法运行完毕时,其对应的栈帧所占用的内存也会自动释放。当JVM方法栈空间不足时,会抛出StackOverflowError的错误,在Sun JDK中可以通过-Xss来指定其大小。

虚拟机栈占用的是操作系统内存,每个线程都对应着一个虚拟机栈,它是线程私有的,而且分配非常高效。一个线程的每个方法在执行的同时,都会创建一个栈帧(Statck Frame),栈帧中存储的有局部变量表、操作站、动态链接、方法出口等,当方法被调用时,栈帧在JVM栈中入栈,当方法执行完成时,栈帧出栈。

局部变量表中存储着方法的相关局部变量,包括各种基本数据类型,对象的引用,返回地址等。在局部变量表中,只有long和double类型会占用2个局部变量空间(Slot,对于32位机器,一个Slot就是32个bit),其它都是1个Slot。需要注意的是,局部变量表是在编译时就已经确定好的,方法运行所需要分配的空间在栈帧中是完全确定的,在方法的生命周期内都不会改变。

虚拟机栈中定义了两种异常,如果线程调用的栈深度大于虚拟机允许的最大深度,则抛出StatckOverFlowError(栈溢出);不过多数Java虚拟机都允许动态扩展虚拟机栈的大小(有少部分是固定长度的),所以线程可以一直申请栈,直到内存不足,此时,会抛出OutOfMemoryError(内存溢出)。

 

2.5 程序计数器(Program Counter Register)(线程私有)

程序计数器是一个比较小的内存区域,可能是CPU寄存器或者操作系统内存,其主要用于指示当前线程所执行的字节码执行到了第几行,可以理解为是当前线程的行号指示器。字节码解释器在工作时,会通过改变这个计数器的值来取下一条语句指令。 每个程序计数器只用来记录一个线程的行号,所以它是线程私有(一个线程就有一个程序计数器)的。

如果程序执行的是一个Java方法,则计数器记录的是正在执行的虚拟机字节码指令地址;如果正在执行的是一个本地(native,由C语言编写完成)方法,则计数器的值为Undefined,由于程序计数器只是记录当前指令地址,所以不存在内存溢出的情况,因此,程序计数器也是所有JVM内存区域中唯一一个没有定义OutOfMemoryError的区域。

 

三、内存溢出与内存泄漏

内存泄漏:分配出去的内存回收不了

内存溢出:指系统内存不够用了

 

1、堆溢出

可以分为:内存泄漏和内存溢出,这两种情况都会抛出OutOfMemoryError:java heap space异常:

 

a、内存泄漏:

内存泄漏是指对象实例在新建和使用完毕后,仍然被引用,没能被垃圾回收释放,一直积累,直到没有剩余内存可用。如果内存泄露,我们要找出泄露的对象是怎么被GC ROOT引用起来,然后通过引用链来具体分析泄露的原因。分析内存泄漏的工具有:Jprofiler,visualvm等。

 

public class OOMTest {  

public static void main(String[] args) {             

        List<UUID> list = new ArrayList<UUID>();  

       while(true){  

            list.add(UUID.randomUUID());  

        }  

    }     

}

看看控制台的输出结果,因为我这边的JVM设置的参数内存足够大,所以需要等待一定的时间,才能看到效果:

 

b、内存溢出

内存溢出是指当我们新建一个实力对象时,实例对象所需占用的内存空间大于堆的可用空间。如果出现了内存溢出问题,这往往是程序本生需要的内存大于了我们给虚拟机配置的内存,这种情况下,我们可以采用调大-Xmx来解决这种问题。

 

public class OOMTest_1 {  

    public static void main(String args[]){  

        List<byte[]> byteList = new ArrayList<byte[]>();  

        byteList.add(new byte[1000 * 1024 * 1024]);  

    }  

}  

2、栈溢出

栈(JVM Stack)存放主要是栈帧( 局部变量表, 操作数栈 , 动态链接 , 方法出口信息 )的地方。注意区分栈和栈帧:栈里包含栈帧。

与线程栈相关的内存异常有两个::

a:StackOverflowError(方法调用层次太深,内存不够新建栈帧)

b:OutOfMemoryError(线程太多,内存不够新建线程)

 

a、java.lang.StackOverflowError

栈溢出抛出java.lang.StackOverflowError错误,出现此种情况是因为方法运行的时候,请求新建栈帧时,栈所剩空间小于栈帧所需空间。例如,通过递归调用方法,不停的产生栈帧,一直把栈空间堆满,直到抛出异常 :

 

public class SOFTest {  

    public void stackOverFlowMethod(){  

        stackOverFlowMethod();  

    }  

    /** 

        

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/151700.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Aurora中的策略模式和模板模式

Aurora中的策略模式和模板模式 在aurora中为了方便以后的扩展使用了策略模式和模板模式实现图片上传和搜索功能&#xff0c;能够在配置类中设置使用Oss或者minio上传图片&#xff0c;es或者mysql文章搜索。后续有新的上传方式或者搜索方式只需要编写对应的实现类即可&#xff…

在原生html中使用less

引入less <link rel"stylesheet/less" href"./lessDemo.less" /><script src"./js/less.min.js"></script> less.min.js文件下载地址:https://github.com/less/less.js 注意&#xff1a;less文件在前&#xff0c;js文件在后…

深入理解强化学习——强化学习的基础知识

分类目录&#xff1a;《深入理解强化学习》总目录 在机器学习领域&#xff0c;有一类任务和人的选择很相似&#xff0c;即序贯决策&#xff08;Sequential Decision Making&#xff09;任务。决策和预测任务不同&#xff0c;决策往往会带来“后果”&#xff0c;因此决策者需要为…

C++ day2

自己封装一个矩形类(Rect)&#xff0c;拥有私有属性:宽度(width)、高度(height)&#xff0c; 定义公有成员函数: 初始化函数:void init(int w, int h) 更改宽度的函数:set_w(int w) 更改高度的函数:set_h(int h) 输出该矩形的周长和面积函数:void show() #include <ios…

2.4 turtle语法元素分析 | Python语言程序设计(嵩天)

文章目录 课程简介第二章 Python基本图形绘制2.4 turtle语法元素分析2.4.1 库引用与import2.4.2 turtle画笔控制函数2.4.3 turtle运动控制函数2.4.4 turtle方向控制函数2.4.5 循环语句与range()函数&#xff08;基本循环语句&#xff09;2.4.6 "Python蟒蛇绘制"代码分…

软件测试基础 - 测试覆盖率

一、覆盖率概念 覆盖率是用来度量测试完整性的一个手段&#xff0c;是测试技术有效性的一个度量。分为&#xff1a;白盒覆盖、灰盒覆盖和黑盒覆盖&#xff1b;测试用例设计不能一味追求覆盖率&#xff0c;因为测试成本随覆盖率的增加而增加。 覆盖率&#xff08;至少被执行一次…

stm32的时钟、中断的配置(针对寄存器),一些基础知识

一、学习参考资料 &#xff08;1&#xff09;正点原子的寄存器源码。 &#xff08;2&#xff09;STM32F103最小系统板开发指南-寄存器版本_V1.1&#xff08;正点&#xff09; &#xff08;3&#xff09;STM32F103最小系统板开发指南-库函数版本_V1.1&#xff08;正点&#xff0…

C++基础——基础语法

1 注释 C支持单行注释和多行注释。 单行注释 // 注释内容单行注释直到改行末尾&#xff0c;可以与代码放在同一行&#xff0c;在代码后面注释 多行注释 /* 注释内容 */包含在其中的都会被注释 2 变量 变量的作用是给指定的内存空间起名&#xff0c;方便操作这段内存。变…

哈希应用之位图

文章目录 1.位图概念2.面试题引入3.代码解决[配注释]4.位图应用4.1找到100亿个整数里只出现一次的整数4.2找两个分别有100亿个整数的文件的交集[只有1G内存]1.法一[使用于数据量<42亿]2.法二[适用于数据量大>42亿]3.在一个有100亿个int的文件中找到出现次数不超过2次的所…

AI伦理:如何确保人工智能的公平与透明

文章目录 什么是AI伦理&#xff1f;AI公平性AI透明性 为什么AI公平性和透明性重要&#xff1f;确保AI公平性的方法1. 数据收集和准备2. 算法和模型3. 解释和可解释性4. 持续监测 确保AI透明性的方法1. 记录决策2. 可解释性工具3. 用户教育 AI伦理的挑战和未来结论 &#x1f389…

STM32MP157汇编流水灯

.text .global _start _start: /* 使能GPIOE、GPIOF寄存器 RCC_MP_AHB4ENSETR * 基地址: 0x50000000 偏移地址: 0xA28 0x50000A28* RCC_MP_AHB4ENSETR[4]->1 RCC_MP_AHB4ENSETR[5]->1*/ LDR R0,0x50000A28LDR R1,[R0]ORR R1,R1,#(0x1<<4)STR R1,[R0]LDR R0,0x…

C++ 学习系列 -- std::list

一 std::list 介绍 list 是 c 中的序列式容器&#xff0c;其实现是双向链表&#xff0c;每个元素都有两个指针&#xff0c;分别指向前一个节点与后一个节点 链表与数组都是计算机常用的内存数据结构&#xff0c;与数组连续内存空间不一样的地方在于&#xff0c;链表的空间是不…

【Java 进阶篇】HTML块级元素详解

HTML&#xff08;Hypertext Markup Language&#xff09;是用于创建网页的标记语言。在HTML中&#xff0c;元素被分为块级元素和内联元素两种主要类型。块级元素通常用于构建网页的结构&#xff0c;而内联元素则嵌套在块级元素内&#xff0c;用于添加文本和其他内容。本文将重点…

异常:找不到匹配的key exchange算法

目录 问题描述原因分析解决方案 问题描述 PC 操作系统&#xff1a;Windows 10 企业版 LTSC PC 异常软件&#xff1a;XshellPortable 4(Build 0127) PC 正常软件&#xff1a;PuTTY Release 0.74、MobaXterm_Personal_23.1 服务器操作系统&#xff1a;OpenEuler 22.03 (LTS-SP2)…

Ubuntu 22.04 安装系统 手动分区 针对只有一块硬盘 lvm 单独分出/home

自动安装的信息 参考自动安装时产生的分区信息 rootyeqiang-MS-7B23:~# fdisk /dev/sdb -l Disk /dev/sdb&#xff1a;894.25 GiB&#xff0c;960197124096 字节&#xff0c;1875385008 个扇区 Disk model: INTEL SSDSC2KB96 单元&#xff1a;扇区 / 1 * 512 512 字节 扇区大…

phpstudy本地域名伪静态

环境&#xff1a;WNMP(Windows10 Nginx1.15.11 MySQL5.7.26 【PHP 7.4.3 (cli) (built: Feb 18 2020 17:29:57) ( NTS Visual C 2017 x64 ) 】) 使用PhpStudy配置本地域名后&#xff0c;设置伪静态&#xff0c;这样在Web端打开网站就不需要输入index.php了&#xff0c;很简单…

架构方法、模型、范式、治理

从架构方法、模型、范式、治理等四个方面介绍架构的概念和方法论、典型业务场景下的架构范式、不同架构的治理特点这3个方面的内容

Pycharm操作git仓库 合并等

菜单 Git CommitPushUpdate ProjectPullFetchMergreRebase 查询 查询分支 查询本地所有分支 # 查询本地分支 git branch# 查询远程分支 git branch -rPycharm查看当前分支 步骤&#xff1a; Git->Branches 哈喽&#xff0c;大家好&#xff0c;我是[有勇气的牛排]&…

ELK集群 日志中心集群

ES&#xff1a;用来日志存储 Logstash:用来日志的搜集&#xff0c;进行日志格式转换并且传送给别人&#xff08;转发&#xff09; Kibana:主要用于日志的展示和分析 kafka Filebeat:搜集文件数据 es-1 本地解析 vi /etc/hosts scp /etc/hosts es-2:/etc/hosts scp /etc…

视频转GIF:快速生成有趣的动态图片

随着社交媒体的快速发展&#xff0c;GIF动态图片已经成为了人们表达情感、分享生活片段的重要方式。将视频片段转换成GIF动态图片&#xff0c;可以让人们更好地分享和表达自己的情感&#xff0c;也可以让一些有趣的瞬间变得更加生动有趣。本文将介绍如何将视频快速转换成GIF动态…