JVM入门(待补充)

JVM架构图

在这里插入图片描述

1.什么是JVM?

①JVM是Java Virtual Machine 的缩写也就是Java虚拟机。
②是Java实现跨平台的基础,JVM中的Java解释器负责将编译之后的字节码文件解释成特定的机器码运行调用操作系统的api。
JVM是JRE的一部分,它是一个虚构出来的计算机,按照定义叫做通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的计算机系统。

2.JDK/JRE

①JRE(Java Runtime Environment)Java运行环境,里面包含了JVM和一些基本的类库
②JDK(Java Development Kit)Java开发工具包,它继承了jre和一些开发使用的工具如javac.exe,java.exe,jar.exe等,但是安装jdk后会发现有两个jre,一个和jdk同级别目录称它为通用jre,另一个在jdk文件夹中成为专用jre。通用jre一般用于执行Java程序或者字节码文件,专用jre用于编译源程序如javac命令时使用

3.JVM结构

①粗略分,JVM的内部体系分为三部分,类加载器运行时数据区执行引擎
A.类加载器:
B.运行时数据区
C.执行引擎

运行时数据区:

Heap(堆)

在这里插入图片描述

  1. Java堆是JVM所管理的内存中最大的一块,并且是所有线程共享的一块内存区域,在JVM启动时创建,用于存放对象实例,几乎所有的对象实例都在堆中分配内存。
  2. 堆是垃圾收集器管理的主要区域,因此也被称为“GC堆”
  3. 年轻代分为EdenSurvival区,Eden区占大量,默认比例为8:1:1
  4. 参数配置
    -Xmx 最大可用内存
    -Xms 当前最大内存
    -Xmn 新生代内存
    -XX:SurvivorRatio=2 新生代内存中Form和Survivor区的比例。
    例:-Xmn1m 则eden:Survivor:Survivor=2:1:1
    所以eden=512KB,from=to=256KB
    -XX:NewRatio=老年代/新生代 老年代与新生代的比例
    例:-Xmx18M -Xms18M -XX:NewRatio=2
    新生代=181/3=6MB 老年代=182/3=12MB
    -XX:HeapDumpOnOutOfMemoryError 内存溢出时导出整个堆信息

虚拟机栈

图中为多个虚拟机栈
在这里插入图片描述

  1. 虚拟机栈用于存放栈帧

  2. 每当启动一个新线程时Java虚拟机都会为它分配一个虚拟机栈,虚拟机栈是一块线程私有的内存空间,生命周期与线程相同,每一次函数调用都会有一个对应的栈帧压入栈中,函数调用结束都会有一个栈帧被弹出Java栈。(函数结束分两种,一是正常执行完毕和return指令,二是抛出异常),每个方法从被调用,直到被执行完。对应着一个栈帧在虚拟机中从入栈到出栈的过程。

  3. 栈帧中包含局部变量表操作数栈帧数据区几个部分
    A. 局部变量表:
    ① 是一组变量值的存储空间,用于存放方法参数局部变量,表中的变量只在当前函数中有效(随着调用结束出栈后销毁
    ② 变量槽是局部变量表的最小单位,一个slot(槽)可以放boolean,byte,char,short,int,float,reference和returenAdress8种类型,reference表示对一个对象实例的引用。而long和double变量,虚拟机会为其分配两个连续的slot
    ③ 栈帧中的slot是可以重用的,例如一个局部变量脱离了其作用域,那么在其作用域之后声明的新局部变量就很有可能重用上一个过期的局部变量的槽位。(影响GC回收https://blog.csdn.net/qq_28666081/article/details/85306719)
    在这里插入图片描述
    B. 操作数栈
    ① 主要用于保存计算过程的中间结果,方法执行中的算数运算或者调用其他方法进行参数传递的时候是通过操作数栈
    ② 据了解:概念模型中两个栈帧是相互独立的,但是大部分虚拟机会进行优化,令两个栈帧出现一部分重叠,令下面部分的操作数栈与上面部分的局部变量表重叠在一块,这样在方法调用中可以共用一部分数据,就无需额外的参数复制传递。
    C. 动态连接(了解)
    ① 每个栈帧都包含一个执行运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。Class 文件中存放了大量的符号引用,字节码中的方法调用指令就是以常量池中指向方法的符号引用作为参数。这些符号引用一部分会在类加载阶段或第一次使用时转化为直接引用,这种转化称为静态解析。另一部分将在每一次运行期间转化为直接引用,这部分称为动态连接。
    D. 方法返回地址(了解)
    ① 当执行遇到返回指令,会将返回值传递给上层的方法调用者,这种退出的方式称为正常完成出口(Normal Method Invocation Completion),一般来说,调用者的PC计数器可以作为返回地址。
    ② 当执行遇到异常,并且当前方法体内没有得到处理,就会导致方法退出,此时是没有返回值的,称为异常完成出口(Abrupt Method Invocation Completion),返回地址要通过异常处理器表来确定。
    ③ 当方法返回时,可能进行3个操作:恢复上层方法的局部变量表和操作数栈,把返回值压入调用者调用者栈帧的操作数栈,调整 PC 计数器的值以指向方法调用指令后面的一条指令
    E.科普常量池:
    ① Java中的常量池分为静态常量池运行时常量池两种
    ② 静态常量池:即为*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数字)字面量,还包含了类、方法信息,占用了class的绝大部分空间
    ③ 运行时常量池:指的是JVM虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中。常说是常量池指的是方法区中的运行时常量池。

-Xss 指定最大栈空间,决定了函数调用的最大深度

补充栈溢出

方法区

方法区是一种规范,永久区和元空间都是此规范下的,所以在1.7移除永久区后方法区没消失

  1. 方法区和堆一样是一块所有线程共享的内存区域,它用于保存系统的类信息,比如类中的方法字段常量池等。方法区的大小决定了系统可以保存多少个类
  2. 在JDK1.7之前方法区可以理解成永久区,使用参数指定大小,默认大小为64MB,那么如果在系统中使用了动态代理,那么有可能在运行时生成大量的类,如果没设置好永久区的大小可能会出现永久区的内存溢出
  3. 在JDK1.7开始永久区被移除,取而代之的是元空间,元空间的大小可以使用参数指定,它是一块堆外内存,所以它的大小是可以动态扩大的,默认情况下JVM的元空间可以耗尽系统内存。元空间存储类的元信息,在中开辟了一块新的区域存放常量池
  4. 永久区和元空间区别?
    A. 存储位置的不同,永久区是堆的一部分和新生代老年代的地址是连续的;而元空间属于本地内存
    B. 存储内容不同,元空间存储类的元信息,静态变量和常量池并入了堆中,相当于永久代的数据被分到了堆和元空间中
  5. 元空间对比永久区的优点?
    将元数据从永久代中剥离出来不仅优于管理,还可以简化Full GC和以后的并发隔离类元数据等方面进行优化。
    原因:永久代的调优很困难,很难确定一个合适的大小,影响因素很多(类数量的多少、常量数量的多少等)
    永久代中的元数据位置会随着一次Full GC发生移动,比较消耗虚拟机性能,同时JVM中的每种类型的垃圾回收器都需要特殊处理永久代中的元数据,

-XX:PermSize 初始永久区大小
-XX:MaxPermSize 最大永久区大小
-XX:MaxMetaspaceSize 最大元空间大小

本地方法栈

  1. 与虚拟机栈作用非常相似,虚拟机栈执行的是java方法,本地方法栈则为虚拟机用到的native方法服务。
  2. Native方法。是一个Java调用非Java代码的接口,如果一个方法描述符有Native,这个描述符将有一个指向该方法的实现指针,这些实现在.dll文件中,但是他们会被操作系统加载到Java程序的地址空间中。

程序计数器

A. 程序计数器是一块相对较小的内存空间,它的作用可以看作是当前线程所执行的字节码的行号指示器,分支、循环、跳转、异常处理、线程恢复都要依赖这个计数器来完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值