JVM笔记

 
 

JVM

JVM是Java Virtual Machine(Java虚拟机)的缩写,Java程序运行在Java虚拟机之上,Java虚拟机运行在操作系统之上,所一说Java是一门跨平台语言,只要在操作系统之上安装JVM就可以运行Java程序。

JVM位置
JVM不光可以执行Java程序,能够编译成Java字节码的程序都可以在JVM上面运行。
字节码文件
 
 

JVM体系结构

JVM架构简图
字节码文件(Class Files):Java字节码类文件(.class)是Java编译器编译Java源文件(.java)产生的“目标文件”。
类加载器子系统(Class Loader Subsystem):负责把字节码文件加载进JVM运行时数据区中。
运行时数据区(Runtime Data Area):Java程序运行时内存空间,该空间包含方法区、堆、程序计数器、本地方法栈、虚拟机栈。
程序计数器(Program Counter Register):占据一块较小的内存空间,可以看做当前线程所执行的字节码的行号指示器。
虚拟机栈(Java Virtual Machine Stack):方法在执行时都需要在栈中创建一个栈帧 ,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用直至完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。
本地方法栈(Native Method Stack):本地方法栈与虚拟机栈所发挥的作用非常相似,他们之间的区别不过是虚拟机栈为虚拟机执行Java方法(字节码)服务,而本地方法栈则为虚拟机中使用到的native方法服务。
堆(heap):堆空间是jvm内存中最大的一块,此内存区域唯一的目的就是存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。
方法区(Method Area):和堆一样所有线程共享,用于存储已被JVM加载类信息、常量、静态变量,即编译器编译后的代码。

 
 

类加载

每个编写的(.java)拓展名类文件都存储着需要执行的程序逻辑,这些(.java)文件经过Java编译器编译成拓展名为(.class)的文件,(.class)文件中保存着Java代码经转换后的虚拟机指令,当需要使用某个类时,虚拟机将会加载它的(.class)文件,并创建对应的class对象,将class文件加载到虚拟机的内存,这个过程称为类加载。

类的加载需要用到类加载器,虚拟机提供了3种类加载器,引导(Bootstrap)类加载器、扩展(Extension)类加载器、应用(App)类加载器。
启动类加载器:主要加载的是JVM自身需要的类,这个类加载使用C++语言实现的,是虚拟机自身的一部分,负责将<JAVA_HOME>/lib路径下的核心类库或-Xbootclasspath参数指定的路径下的jar包加载到内存中。
扩展类加载器:由Java语言实现,负责加载<JAVA_HOME>/lib/ext目录下或者由系统变量-Djava.ext.dir指定位路径中的类库,开发者可以直接使用标准扩展类加载器。
应用类加载器:程序中默认的类加载器,负责加载应用类类路径java -classpath或-D java.class.path 指定路径下的类库。

双亲委派模式
在Java的日常应用程序开发中,类的加载是由各种类加载器相互配合执行的,Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象,而且加载某个类的class文件时,Java虚拟机采用的是双亲委派模式即把请求交由父类加载器处理,当父类加载失败时才由子类加载器加载。
双亲委派模式
优势
使Java类随着它的类加载器一起具备了一种带有优先级的层次关系
一、避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次。
二、防止核心API库被随意篡改:核心API会去JAVA_HOME目录加载,不会在当前项目目录加载。

 
 

方法的调用通过栈实现,但方法执行完毕后会推出栈,调用方法继续执行,只有栈顶方法才能执行。每个方法对应一个栈帧,栈帧包含局部变量表、方法返回地址等运行时元素。
栈帧结构
下图为方法运行过程中变量、对象等数据存储布局。
对象的内存布局

 
 

堆
堆是虚拟机中占据空间最大的区域,当一个方法要创建对象或者数组时就会在堆中生成该对象,该对象被栈中引用变量引用,当该方法执行完毕推出栈帧后生成对象依然存在,需要垃圾回收线程清理,所以垃圾回收区域主要在堆中进行。堆空间可再次划分为年轻区、老年区、元空间,创建对象在年轻代生成,多次垃圾回收后依然使用的对象被认为常用对象,移入老年区。方法区在元空间实现。

 
 

垃圾回收

堆为一块区域,为了高效回收内存,所以把堆分成年轻区和老年区,年轻区使用轻GC垃圾回收方法,老年区使用重GC回收方法。
堆
轻GC垃圾回收方法:
年轻区生成对象存活率低,所以轻GC垃圾回收方法为复制算法。
复制算法

对象在伊甸园区生成,第一次垃圾回收时会把幸存下来的对象移至幸存区to,新对象继续在伊甸园区产生,再次出发垃圾回收时,会把伊甸园区和幸村去from幸存的对象移至幸村区to。回收过期对象所占空间。
该方法执行效率高但是内存使用率低,适用于回收率高的青年区。

重GC垃圾回收方法:
老年区中对象相对稳点,所以采用标记清除+标记清除压缩方法。
标记清除算法
因为老年区中对象相对较稳点,为提高内存使用率,所以使用标记清楚算法,第一遍扫描该区域标记处需要清除对象,第二遍扫描该区域清除标记对象,该方法会产生很多内存碎片,为改善内存整齐度会触发标记清除压缩方法对内存空间进行整理。

 

JVM调优

JVM调优主要针对堆内存的分配,为提高垃圾回收效率,可对堆中年轻代和老年代的内存分配进行配置,在一些大量产生临时对象的任务中,比如数据解析、订单处理,生成的对象一般存活不到一秒,除了选择不同的垃圾回收方法,还可以增加年轻代内存,减少老年代内存,增加年轻代内存可以减少轻GC次数,因为对象存活时间短,每次轻GC回收的对象数量相等,总的来说可以减少对象回收的数量,提高垃圾回收效率,增大年轻代也在一定程度上避免伊甸园区对象直接进入老年代,老年代垃圾回收较慢。

java -Xmx1G -Xms1G -jar xxx.jar

# -Xms:初始Java堆大小
# -Xmx:最大Java堆大小
# -Xmn:设置年轻代大小
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值