浅谈JVM---JVM内存机制

这里写目录标题

  • JVM的运行机制
    • Java程序的具体运行过程如下
  • Java的多线程
    • 在JVM后台运行的线程主要有
  • Java内存区域
    • JVM内存区域--程序计数器
    • 虚拟机栈
    • 本地方法区,堆
    • 方法区
    • JVM堆
      • MinorGC

JVM的运行机制

  • JVM(Java Virtual Machine)是用于运行Java字节码的虚拟机,Java虚拟机栈,虚拟机堆,本地方法区,程序计数器,本地方法栈
  • JVM运行在操作系统之上不和硬件设备直接交互。
  • Java源文件在通过编译器之后被编译成相应的.Class文件(字节码文件),.Class文件又被JVM中的解释器编译成机器码,在不同的操作系统上运行。
  • 每种操作系统的解释器是不同的但基于解释器实现的虚拟机是相同的,这就是Java能跨平台的原因。
  • 在一个Java进程开始运行后,虚拟机就开始初始化了,有多少个进程启动,就会实例多少个虚拟机实例。进程退出或者关闭则虚拟机实例消亡。在多个虚拟机实例之间不能共享数据。

Java程序的具体运行过程如下

  • Java源文件被编译成字节码文件
  • JVM将字节码文件编译成相应操作系统的机器码
  • 机器码调用相应操作系统的本地方法库执行相应的方法

Java虚拟机包括一个类加载器子系统(Class Loader SubSystem),运行时加载区(Runtime Data Area),执行引擎和本地接口库(Native Interface Library)
本地接口库通过调用本地方法库(Native Method Library)与操作系统交互。

浅谈JVM---JVM内存机制_第1张图片

  • 方法区包含运行时常量池
  • 虚拟机堆里1/3空间是新生代,2/3是老年代
  • 虚拟机栈里包含栈帧

框图说明:

  1. 类加载子系统用于将编译好的.class文件加载到jvm中
  2. 运行时数据区用于存储在JVM运行过程中产生的数据。包括程序计数器,方法区,本地方法区虚拟机栈和虚拟机堆。
  3. 执行引擎包含即时编译器(JITCompiler)和垃圾回收器(GarbageCollection)。即时编译器用于将Java字节码编译成具体的机器码,垃圾回收器用于回收运行过程中不再使用的对象
  4. 本地接口用于调用操作系统的本地方法库完成具体的指定操作

Java的多线程

在多核操作系统中,JVM允许在一个进程内同时并发执行多个线程。JVM的线程与操作系统的线程是相对应的,在JVM线程的本地存储,缓冲区分配,同步对象,栈,程序计数器等准备共工作完成时。JVM会调用操作系统的接口,创建一个与之对应的原生线程;在JVM线程运行结束时原生线程随之被收回。而操作系统负责调度所有线程,并为其分配CPU时间片,在原生操作系统初始化完毕时。就会调用Java线程的run执行该线程;在线程结束时会释放原生线程和Java线程所对应的资源。(一个线程大约占用128k的空间。)

在JVM后台运行的线程主要有

  • 虚拟机线程:虚拟机线程在JVM到达安全点时出现
  • 周期性任务线程:通过定时器调度线程来实现周期性操作的执行
  • GC线程:GC线程支持JVM中不同的垃圾回收
  • 编译器线程:在运行时将字节码动态的编译成本地平台机器码,是JVM跨平台的具体实现
  • 信号分发线程:接收发送到JVM的信号,并调用JVM方法。

Java内存区域

浅谈JVM---JVM内存机制_第2张图片

  • 线程的私有区域的生命周期与线程相同,随线程的启动而创建,随线程的结束而销毁。在JVM内,每个线程都与操作系统的本地线程直接映射,因此这部分内存区域的存在与否和本地线程的启动和销毁对应。
  • 线程共享区域随虚拟机的启动而创建,随虛拟机的关闭而销毁。
  • 直接内存也叫做堆外内存,它并不是JVM运行时数据区的一部分,但在并发编程中被频繁使用。

JVM内存区域–程序计数器

  • 程序计数器属于线程私有的内存区域,他是唯一没有Out Of Memory(内存溢出)的区域
  • 线程计数器是一块很小的内存空间,用于存储当前运行的线程所执行的字节码的行号指示器。每个运行中的线程都有一个独立的程序计数器。在方法正在执行时,该方法的程序计数器记录的是实时虚拟机字节码指令的地址;如果该方法执行的Native,也就是本操作系统的原生方法则程序计数器值为空。

虚拟机栈

用来存储变量,操作数栈,动态链接,出口方法等信息。
栈帧:用来记录方法的执行过程在方法被执行时虚拟机会为其创建一个与之对应的栈帧。方法的执行和返回对应栈帧在虚拟机中的入栈和出栈。
浅谈JVM---JVM内存机制_第3张图片

本地方法区,堆

  • 本地方法区是线程私有的,和虚拟机栈的作用类似,区别在于虚拟机栈为执行Java方法调用;本地方法栈为Native方法服务。
  • 堆也叫做运行时数据区是线程共享的:在JVM运行过程中创建的对象和产生的数据都被存储在堆中。堆是被线程共享的内存区域,也是垃圾收集器进行垃圾回收最主要的内存区域。
  • 现代JVM采用分代收集算法,因此Java堆从GC的角度还可以细分为新生代,老年代和永久代。

方法区

是线程共享的。方法区被称为永久代用于存储下图的各种属性
浅谈JVM---JVM内存机制_第4张图片

JVM堆

浅谈JVM---JVM内存机制_第5张图片
但是在Java8中永久代已经被元数据区取代。元数据区的作用和永久代相似,区别是:元数据区并没有使用虚拟机的内存,而是直接使用操作系统的本地内存。因此,元空间的大小不再受JVM内存的限制,只和操作系统的内存有关。

MinorGC

新生代的GC过程叫做MinorGC,采用复制算法,具体过程:

  1. 如果某对象的年龄达到老年代的标准,将其复制到老年代,同时把这些对象的年龄加1;如果ServivorTo区的内存空间不够,则也直接将其制到老年代;如果对象属于大对象(大小为2K~ 128K的对象属于大对象),则也直接将:其复制到老年代。
  2. 清空Eden区和Serv ivorFrom区中的对象。
  3. 将ServivorTo区和ServivorFrom区互换,原来的Serv ivorTo区成为下一次GC时的ServivorFrom区。

新生代垃圾回收的过程
基于新生代中的对象在经历过一次GC后,大多数对象都会被回收的假设,新生代垃圾会采用复制的策略:

  1. 在GC刚开始的时候,Survior的To空间是空的,对象只能存在于Eden或者From。

  2. 随着GC的进行,

    2.1 Eden空间依然被引用的对象将被移动到To空间。

    2.2 From空间,这个空间中依然被引用的对象的处理依赖于它们的存活了的多少时间。如果它们的存活周期没有达到某个阀值(tenuring threshold,表示经历了几次GC依然存活),那 么它们也要被移动到To,否则它们将被移动到老年代。

  3. 当这个copy的过程结束后,Eden和From空间中的对象是可被回收了(新生代所有存活下来的对象要么去了To,要么去了老年代)。在Eden,From向To空间移动的过程中,To空间有可能满了,那么剩下的对象,将直接移动到老年代。

  4. 最后一步,From和To交换角色,因此在下一轮GC开始时,To是空的,而From则包含了所有新生代上轮GC时存活下来的对象。

下图所示是新生代GC开始时的状态以及GC结束时的状态
浅谈JVM---JVM内存机制_第6张图片

你可能感兴趣的:(java,jvm)