JVM内存模型深度刨析与常见参数优化 您所在的位置:网站首页 Java虚拟机参数 JVM内存模型深度刨析与常见参数优化

JVM内存模型深度刨析与常见参数优化

2023-04-02 22:08| 来源: 网络整理| 查看: 265

jdk体系结构图

在这里插入图片描述 java lanagunage:最上层是java语言

Tools & Tools APLS:指令工具箱,手动编译java源码的时候会用到,如javac编辑字节码程序 ,java执行字节码程序,javadoc生成Java文档

JRE:是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。JDK是程序员使用java语言编写java程序所需的开发工具包,是提供给程序员使用的。运行java程序只需安装JRE。如果需要编写java程序,需要安装JDK。

JAVA VirTual Machine:java运行时最重要的基础时java虚拟机,也就是上图的Java Virtual Machine, 这是java代码一次编译到处运行的基础,java程序实际上时运行在虚拟机上的。

jdk和jre的区别为:JRE是java运行时环境而JDK是java开发工具包,JDK包含JRE,但是JRE可以独立安装。

java跨平台特性

在这里插入图片描述

jvm内存模型

在这里插入图片描述

程序计数器

当前线程所执行的行号指示器,字节码解释器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能,都需要依赖这个计数器来完成

由于JVM的多线程是通过线程轮流切换来分配CPU执行时间的方式实现的,一个CPU只能处理一个线程的业务。线程切换后,程序计数器会记录当前线程执行的字节码指令的地址(行号),当线程再次分配到CPU时,通过程序计数器记录的行号找到上次字节码执行的地址继续执行。程序计数器是线程私有的,它是JVM中唯一没有规定OutOfMemoryError情况的区域。

栈(java虚拟机栈)

每个方法在执行的同时在java虚拟机栈里面创建一个栈帧用来存储局部变量表,操作数栈,动态链接,方法出口等信息。

栈帧:栈帧是虚拟机的单位,一个方法一个栈帧,用来储存局部变量、操作数栈、动态链接、方法出口等信息

局部变量表:用来存储我们临时8个基本数据类型、对象引用地址、returnAddress类型(字节码的指令地址)

操作数栈:操作数栈就是用来操作的,例如代码中有个 i = 6*6,他在一开始的时候就会进行操作,读取我们的代码,进行计算后再放入局部变量表中去

动态连接:如方法中需要大量计算的,把计算的代码封装成一个add()方法,当前方法调用add()方法,跳转过去,add()就是动态链接

方法出口:出口正常的话就是return,不正常的话就是抛出异常

本地方法栈

与虚拟机栈一样,只不过虚拟机栈式服务java方法的,而本地方法栈是位虚拟机调用Native方法的。

java堆

java 虚拟机中最大的一块内存,是被所有线程共享的,几乎所有对像实例都在这里分配。

方法区

用来存储已被虚拟机加载过的类信息,常量,静态变量,即使编译后的代码等。

jvm 参数设置

在这里插入图片描述 Spring Boot程序的JVM参数设置格式(Tomcat启动直接加在bin目录下catalina.sh文件里): java -Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:MateSpaceSize=256M -XX:MaxMatespaceSize=256M -jar xxx.jar

关于原空间的参数有两个:-XX:MatespaceSize=N -XXMaxMatespaceSize=N -XX:MaxMetaspaceSize: 设置元空间最大值, 默认是-1, 即不限制, 或者说只受限于本地内存大小。 -XX:MetaspaceSize: 指定元空间触发Fullgc的初始阈值(元空间无固定初始大小), 以字节为单位,默认是21M,达到该值就会触发 full gc进行类型卸载, 同时收集器会对该值进行调整: 如果释放了大量的空间, 就适当降低该值; 如果释放了很少的空间, 那么在不超 过-XX:MaxMetaspaceSize(如果设置了的话) 的情况下, 适当提高该值。这个跟早期jdk版本的-XX:PermSize参数意思不一样,- XX:PermSize代表永久代的初始容量。 由于调整元空间的大小需要Full GC,这是非常昂贵的操作,如果应用在启动的时候发生大量Full GC,通常都是由于永久代或元空间发生 了大小调整,基于这种情况,一般建议在JVM参数中将MetaspaceSize和MaxMetaspaceSize设置成一样的值,并设置得比初始值要大, 对于8G物理内存的机器来说,一般我会将这两个值都设置为256M。

StackOverflowError示例: // JVM设置 -Xss128k(默认1M) public class StackOverflowTest { static int count = 0; static void redo() { count++; redo(); } public static void main(String[] args) { try { redo(); } catch (Throwable t) { t.printStackTrace(); System.out.println(count); } } } 运行结果: java.lang.StackOverflowError at com.tuling.jvm.StackOverflowTest.redo(StackOverflowTest.java:12) at com.tuling.jvm.StackOverflowTest.redo(StackOverflowTest.java:13) at com.tuling.jvm.StackOverflowTest.redo(StackOverflowTest.java:13)

结论: -Xss设置越小count值越小,说明一个线程栈里能分配的栈帧就越少,但是对JVM整体来说能开启的线程数会更多

jvm参数案例

在这里插入图片描述 结论:通过上面这些内容介绍,大家应该对JVM优化有些概念了,就是尽可能让对象都在新生代里分配和回收,尽量别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有