WatchDogs

Knowledge of Backend Development

0%

Java Virtua Machine
Java 虚拟机
虚拟机组成部分:

-类加载子系统 Class Loader SubSystem
将编译好的Class文件加载到JVM中
-执行引擎

  • 即时编译器
  • 垃圾回收器

-本地接口库 Native Interface Library
调用操作系统本地方法库完成具体指令
-运行时数据区 Runtime Data Area

  • 程序计数器
  • 方法区
    1.7时使用永久代实现,1.8中,数据被分到了元数据区和堆中,元空间存储类的元信息,静态变量和常量池等并入堆中。其中元空间不属于JVM内存区域,属于本地内存
    类名,访问修饰符,常量池,字段描述,方法描述
  • 虚拟机栈
    栈帧:局部变量表,操作数栈,动态链接,方法出口
  • 本地方法区

Java程序的运行过程:
1.Java源文件被编译器编译成字节码文件
2.JVM将字节码文件编译成相应操作系统机器码
 每种操作系统的解释器都是不同的,但基于解释器实现的虚拟机是相同的,这也是JAVA能够跨平台的原因
3.机器码调用响应操作系统的本地方法库执行相应的方法。

在一个Java进程开始运行后,虚拟机就开始实例化了,有多个进程启动就会实例化多个虚拟机。进程退出或关闭,虚拟机消亡。多个虚拟机之间不能共享数据


Java 运行时数据区

  • 程序计数器(线程私有
  • 虚拟机栈(线程私有
  • 本地方法区(线程私有
  • 方法区
  • 直接内存

线程私有区域的生命周期与线程相同,随线程的启动而创建,随线程的结束而销毁。在JVM内,每个时线程都与操作系统本地线程直接映射,因此这部分内存区域的存在与否和本地线程的启动销毁对应。

线程共享区域随JVM的启动而创建,随JVM的关闭而销毁。

直接内存
也叫堆外内存,他不是JVM运行时数据区的一部分,但在并发编程中被频繁使用。JDK的NIO模块就是基于堆外内存,NIO通过调用本地方法直接在操作系统上分配堆外内存。

程序计数器(线程私有区域)
一块很小的内存空间,用于存储当前运行线程所执行的字节码的行号指示器。每个线程都有一个独立的程序计数器。方法正在执行时,记录的是实时虚拟机字节码指令的地址。如果是Native方法,则程序计数器为空Undefined。唯一一块没有OOM(Out of Memory)的区域。

虚拟机栈(线程私有区域)
虚拟机栈是描述Java方法执行过程的内存模型,它在当前栈帧中存储了局部变量表,操作数栈,动态链接,方法出口等。
我们平常写的递归方法就是离用了虚拟机栈,他的栈帧为我们保存了运行数据。
每个方法的运行和返回都对应了入栈和出栈。每个运行的线程只有一个栈帧处于活动状态。

本地方法区(线程私有区域)
作用和虚拟机栈类似,但本地方法栈是Native方法使用的区域。

堆(线程共享区域)
JVM运行过程中创建的对象和产生的数据都被存储在堆中。堆是线程共享区域,也是垃圾回收的主要区域
因为JVM采用分代收集法,堆还能被分为:

  • 新生代1/3

-Eden区8/30
-ServivorFrom区1/30
-ServivorTo区1/30

  • 老年代2/3
  • 永久代(1.7之前,方法区的实现,1.8之后仅有静态变量和常量池留在堆中,类的元信息被放到本地内存的元空间中)

新生代
JVM新创建的对象会被放在新生代

老年代
新生代达到一定寿命,或者创建时就占空间大的对象被放在老年代。

永久代(元数据区):存储已被虚拟机加载的类信息(Class),常量,静态变量,即时编译器编译后的代码等数据