JVM内存模型

JVM简单了解

Java的跨平台性

Java的跨平台性,能够实现跨平台的是Java程序,而不是JVM,JVM是用C/C++开发,是编译之后的机器码,无法实现跨平台,不同的平台下需要安装不同的JVM.
而写好的Java程序,编译之后会生成字节码文件,即.class文件,JVM就是负责将字节码文件翻译成特定平台下的机器码然后运行,在不同的平台上安装对应的JVM,就可以来U运行字节码文件,通过这一“中间层”,在不同平台上运行Java程序,实现“一次编译,到处运行”的目的

JVM概念

JVM 即Java Virtual Machine,Java虚拟机
JVM是Java的核心和基础,在Java编译器和OS平台之间的虚拟的处理器,是一种利用软件方法来实现的抽象的计算机的下层的操作系统和硬件平台,在其上面执行java的字节码程序
JVM有自己的完善的硬件架构,如处理器,堆栈,寄存器,还有相应的指定系统,使用JVM可以实现开发和操作系统的无关,实现跨平台性

JDK/JVM/JRE是什么关系

JRE(Java Runtime Environment ,Java的运行环境),也就是Java平台所有的Java程序都是要在JRE下才能运行
JDK(Java Development Kit,Java开发工具包),程序开发过程中用来编译、调试Java程序用的Java开发工具包,JDK的工具包也是Java程序,也是需要在JRE上运行,为了保证JDK的独立性和完整性,在JDK安装过程中,JRE也是安装的一部分 ,所在在JDK安装的过程中有一个jre的目录,主要存放的是JRE的文件
JVM(Java Virtual Machine,Java虚拟机)是JRE的一部分,是一个虚拟出来的计算机,通过实际的计算机来仿真模拟各种计算机的功能
在这里插入图片描述

Java 内存模型

在这里插入图片描述
内存划分为:
方法区:线程共享的
堆区:线程共享,存放对象

虚拟机栈:线程私有,存放的是线程运行时局部变量等
本地方法栈:线程私有的,native方法
程序计数器:线程私有的
线程私有的内存区域:生命周期都是和线程同步

程序计数器

程序计数器是一块较小内存空间,用来记录当前程序所执行的字节码的行号
字节码解释器工作时通过改变这个计数器的值来选取下一条要执行的字节码指令,分支,循环,跳转,异常处理等都需要依赖这个程序寄之前来完成。
线程切换后也需要恢复到正确的执行位置,因此,每一个线程都有一个独立到的程序计数器,各个线程的计数器相互独立,互不影响,因此线程计数器是必须私有的

作用:

1、字节码解释器通过改变程序计数器来依次读取执行,从而实现代码的流程控制
2、在多线程下,程序计数器用于记录当前线程执行的位置,方便在程序切换后能够继续正确执行

注意:程序计时器是唯一一个不会抛出OutOfMemoryError的(OOM)内存区域
程序计数器的生命周期是和线程同步的,随着线程的创建而创建,随着线程的消亡而死亡

虚拟机栈

与程序计数器一样,虚拟机栈也是线程私有的,生命周期和线程相同
在这里插入图片描述
注意:在程序执行过程中,可以理解为方法调用方法,每一个方法在虚拟机栈上对应就是一个栈帧,
每一个栈帧包好信息:局部变量表、操作数栈、动态链接、方法出口信息
局部变量表:主要存放编译器可知的各种数据类型(boolean、byte、char、short、int、float、double、long),对象的引用(Reference类型,他不是对象本身,是一个执行对象起始位置的引用指针,也可以是指向一个代表对象的句柄)
虚拟机栈会出现两种异常:StackOverflowError和OutOfMemoryError
StackOverflowError:若虚拟机栈的大小不允许动态扩容,当线程请求的栈深度超过当前虚拟机栈的最大深度的时候,就会出现StackOverflowError的异常
OutOfMemoryError:若虚拟机栈的大小允许动态扩容,当前的线程请求栈是内存用完了,无法再动态扩容了,此时抛出OutOfMemoryError异常
虚拟机栈是线程私有的,生命周期随着线程创建而创建,随着线程消亡而死亡

java虚拟机所管理的内存区域最大的一个内存空间就是堆,是线程共享的一块内存区域,在虚拟机启动的时候创建,内存区域用来存放对象实例,几乎所有的对象实例以及数据都在这里分配内存
GC区域即垃圾回收主要作用的就是对象实例,因此GC所作用的区域就是堆区域,
从垃圾回收的角度,堆可以细分为新生代和老年代
新生代细分为:Eden空间,From Survivor空间和To Survivor空间,更细的划分是尾了更高的回收内存或更快的分配内存
永久代:
在jdk 1.6及之前,常量池就存在永久代
在JDK1.7是,有,逐步去“永久代”
在JDK 1.8之后,无永久代, 取而代之的是一个“元空间”(Metaspace)区域,永久代是属于JVM堆中的内存空间,元空间使用的物理内存,直接受到本机的物理内存限制
在这里插入图片描述

方法区

方法区和堆一样,是线程共享的区域,存储被虚拟机加载的类信息,常量,静态变量即时编译器编译后的代码等数据都存放在方法区
生命周期和堆相同,随着JVM的创建而创建随着JVM的消亡而消亡
也会抛出OutOfMemoryError的异常

永久代:

在jdk 1.6及之前,常量池就存在永久代
在JDK1.7是,有,逐步去“永久代”
在JDK 1.8之后,无永久代, 取而代之的是一个“元空间”(Metaspace)区域,永久代是属于JVM堆中的内存空间,元空间使用的物理内存,直接受到本机的物理内存限制
在这里插入图片描述

永久代和元空间的区别

永久代和元空间存储位置和存储内容的区别:
存储位置不同,永久代是堆中的一部分,和新生代,老年代的地址是连续的,而元空间使用本地内存
永久代的大小比较小,元空间的大小取决于本地内存
永久代容易出现OOM,而元空间一般不会
元空间存储类的元信息,静态变量和常量池移入其中。相当于永久代的数据被分割到元空间和堆中

为什么要把永久代替换为元空间

Java原来是属于Sun公司的,后来Java被Oracle收购了。Sun公司实现的Java中的JVM是Hotspot。后来Oracle收购了Java之后,也同时想把Hotspot和JRockit合二为一。他们俩很大的不同,就是方法区的实现。
字符串存在永久代中,容易出现性能问题和永久代内存溢出
类及方法的信息比较难确定大小,因此对于永久代大小的指定比较困难,太小容易出现永久代内存溢出,太大容易出现老年代内存溢出
永久代增加GC复杂度,并且回收效率偏低

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值