JVM整体结构及内存模型分析

JVM整体结构及内存模型

官方介绍链接

JVM内存参数设置

spring-boot 程序的JVM参数设置格式(tomcat启动直接加载bin目录下catalina.sh文件中):

java ‐Xms2048M ‐Xmx2048M ‐Xmn1024M ‐Xss512K 
‐XX:MetaspaceSize=256M ‐XX:MaxMetaspaceSize=256M 
‐jar microservice‐eureka‐server.jar

关于元空间的JVM参数有两个:

  • -XX:MetaspaceSize=N (设置元空间的最大值,默认为-1即不限制,其实是受限于本地内存大小)
  • -XX:MaxMetaspaceSize=N(指定元空间出发full GC的初始阈值(元空间无固定初始大小),以字节为单位,默认是21M,达到该阈值就会出发fullgc进行类型卸载,同时收集器会对该值进行调整:如果fullgc后释放了大量的空间,就适当降低该值;如果fullgc后释放了少量的空间,那么在不超过maxMetaspaceSize的情况下,适当提高该值。这个和早早起-XX:PermSize参数的意思不一样,permSize代表了永久代的初始容量)
    由于调整元空间需要fullgc,fullgc是一个很昂贵的操作,如果在启动的时候就发生了大量的fullgc,通常是由于永久代或者元空间发生了大小调整,基于这种情况,一般建议再JVM的参数中奖MetaspaceSize和MaxMetaspaceSize设置成一样的值,则当元空间的大小大于本地内存的大小时候才开始fullgc,这个需要设置的比初始值要大,对于8G内存的机器来说,一般这个值设置成256M是比较合理的。

JVM运行时数据区结构

  1. 程序计数器(The pc(program counter) Register)

    官方解释:The Java Virtual Machine can support many threads of execution at once (JLS §17). Each Java Virtual Machine thread has its own pc (program counter) register. At any point, each Java Virtual Machine thread is executing the code of a single method, namely the current method (§2.6) for that thread. If that method is not native, the pc register contains the address of the Java Virtual Machine instruction currently being executed. If the method currently being executed by the thread is native, the value of the Java Virtual Machine’s pc register is undefined. The Java Virtual Machine’s pc register is wide enough to hold a returnAddress or a native pointer on the specific platform.
    解释说明:程序计数器就是一个记录当前线程锁执行的字节码的行号指示器,简单的来说就是记录这个线程跑到哪里了。如果程序是单线程的,则程序计数器并没有实际的意义,代码会一直按照顺序沿着指令执行下去,但是jvm是支出多线程的,当某一个线程执行一半被挂起再次获取到时间片重新执行的时候必须知道它上次执行到哪个地方,因此程序计数器是具备线程隔离的特性,每个线程都有自己的程序计数器。

  2. JVM栈(线程栈)(Java Virtual Machine Stacks)

    解释说明:java虚拟机栈也是具备线程隔离性的,随着每个线程的创建而创建,随着线程的销毁而销毁,线程中的每个方法都会在这个栈中创造一个栈帧(Stack Frame),每个栈帧有自己存储局部变量的表,操作数栈,动态连接,方法出口等信息,每一个方法从调用直到方法执行完毕,就对应着一个栈帧在虚拟机中入栈到出栈的过程。

    • 局部变量表(Local Variable Table)
      用来存放方法参数和方法内部定义的局部变量。
    • 操作数栈(Operand Stack)
      操作数栈是一个后入先出的栈,方法的执行操作都在操作数栈中完成,每一个字节码向操作数栈中写入和写出,就是操作数栈的入栈和出栈。
    • 动态连接(Dynamic Linking)
      每个栈帧都有一个指向运行时常量池(JVM运行时的数据区域)中该栈所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接。在Class文件格式的常量池中存有大量的符号引用(1、类的全限定名,2、字段名和属性,3、方法名和属性),字节码中的方法调用指令就是以常量池中指向方法的符号引用为参数。
    • 方法出口(Method Invocation Completion)
      只有两种方法可以退出正在执行的方法,一个是执行引擎遇到方法返回字节码指令(return),这个时候会有返回值返回给方法的调用者,这种退出方法称为正常完成出口(Normal Method Invocation Completion)。另一种退出方式是方法遇到了异常并且在此方法体重没有得到处理,无论是JVM虚拟机自己产生的异常或者是试用throw字节码指令产生的异常,只要是在本方法中没有得到处理的异常,在本方法的异常处理器表中没有搜索到匹配的异常处理器,这种导致方法退出的方式称为异常完成出口(Abrupt Method Invocation Completion),这种方式的退出不会给方法的调用者任何返回值。
  3. 堆(Heap)
    官方解释: The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.
    The heap is created on virtual machine start-up. Heap storage for objects is reclaimed by an automatic storage management system (known as a garbage collector); objects are never explicitly deallocated. The Java Virtual Machine assumes no particular type of automatic storage management system, and the storage management technique may be chosen according to the implementor’s system requirements. The heap may be of a fixed size or may be expanded as required by the computation and may be contracted if a larger heap becomes unnecessary. The memory for the heap does not need to be contiguous.
    A Java Virtual Machine implementation may provide the programmer or the user control over the initial size of the heap, as well as, if the heap can be dynamically expanded or contracted, control over the maximum and minimum heap size.
    The following exceptional condition is associated with the heap:
    If a computation requires more heap than can be made available by the automatic storage management system, the Java Virtual Machine throws an OutOfMemoryError.
    解释说明: 堆是随着java虚拟机产生的时候产生,生命周期是和虚拟机一样,并且是所有线程共享,里面的对象是有垃圾回收器回收,对象永远不会显式的释放,堆的大小可以是固定的也可以动态的扩展,甚至还可以收缩,堆的内存的存放也不是连续的内存。超过堆的内存大小,jvm会报OutOfMemoryError,堆中存放的对象本身而不是对象的引用。

  4. 方法区(Method Area)
    方法区在逻辑上是堆的一部分,但是方法区默认的是不进行垃圾回收或压缩的,所有方法区有个别名(non-heap)这里存放的是一些静态变量、类元信息(每个类的名称,方法信息、字段信息)、常量以及编译后的代码。

  5. 运行常量池(Run-Time Constant Pool):其实是方法区的一部分
    方法区中有个运行时常量池:是每一个类或接口的常量池的运行时表现形式,在类和接口被加载到JVM中后,对应的常量池就被创建出来,在运行期间也可以将新的常量放入常量池中。

  6. 本地方法栈(Native Method Stacks)
    和java虚拟机栈的作用差不多,只不过是为JVM使用到的native方法进行服务的。(methods written in a language other than the Java programming language),和java虚拟机栈一样,可以固定大小也可以动态扩展或收缩,使用的时候内存不够会报StackOverflowError,扩展的时候可用内存不够会报OutOfMemoryError。

每日上亿点击,订单百万的网站JVM设置

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JVMJava虚拟机)的内存结构主要包括以下几个部分: 1. 方法区(Method Area):用于存储类的结构信息,如类的字段、方法、常量池等。方法区是所有线程共享的。 2. 堆(Heap):用于存储对象实例。堆是所有线程共享的,是Java程序中动态分配内存的主要区域。 3. 虚拟机栈(VM Stack):每个线程在执行Java方法时都会创建一个栈帧,用于存储局部变量、操作数栈、方法出口等信息。 4. 本地方法栈(Native Method Stack):与虚拟机栈类似,但是用于执行本地方法(非Java代码)。 5. 程序计数器(Program Counter Register):用于记录当前线程执行的字节码指令地址。 此外,JVM还有一些其他的内存区域,如直接内存(Direct Memory)和运行时常量池(Runtime Constant Pool)等。 关于JVM内存模型,它定义了多线程并发访问内存时的行为规范。JVM内存模型主要包括以下几个概念: 1. 主内存(Main Memory):所有线程共享的内存区域,包含堆、方法区等。 2. 工作内存(Working Memory):每个线程独享的内存区域,包含虚拟机栈、本地方法栈等。 3. 内存间交互操作:线程之间通过主内存进行数据的共享和通信。 4. 原子性、可见性和有序性:JVM保证特定操作的原子性(不可分割)、可见性(一个线程对共享变量的修改对其他线程可见)和有序性(指令重排序的限制)。 5. happens-before关系:JVM定义了happens-before关系来规定多线程之间操作的执行顺序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值