java核心知识点整理——JVM

1、线程

这里所说的线程是指程序执行中的一个线程实体。JVM允许一个应用并发执行多个线程。

HotspotJVM中的Java线程与原生的操作系统中的线程有直接的联系关系。当本地存储、缓存分配区、同步对象、栈和程序计数器等准备好以后,就会创建一个操作系统原生的线程。

JAVA线程结束以后,原生线程即被回收。操作系统负责分配线程,并把他们分配到任何可用的cpu上。当原生线程初始化完毕,就会调用java的run方法。当线程结束时,会释放原生线程和java线程的所有资源。

HotSpotJVM后台运行的系统线程主要有下几点:java核心知识点整理——JVM

 2、JVM内存区域

java核心知识点整理——JVM

JVM内存区域主要分为线程私有区域【程序计数器、虚拟机栈、本地方法区】、线程共享区域【JAVA堆、方法区】、直接内存。

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

线程共享区域随虚拟机的启动/关闭而创建/销毁。

直接内存并不是JVM运行时数据区的一部分,但也会被频繁的使用,在JDK1.4运入的NIO提供了基于Channel和Buffer的IO的方式,他可以使用native函数库直接分配堆外内存,然后使用DirectByteBuffer对象作为这块内存的引用进行操作(详见:java I/O扩展),这样就避免了在JAVA堆和Native堆中来回复制数据,因此在一些场景中可以提高性能。

java核心知识点整理——JVM

 

 2.1、程序计数器(线程私有)

一块较小的内存空间,是当前线程所执行的字节码的行号指示器,每条线程都需要有个独立的程序计数器,这块内存也被成为"线程私有"的内存。

正在执行java方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果还是Native方法,则为空。

这个内存区域是唯一一个在虚拟机中没有规定任何OutOfMemoryError的区域。

2.2、虚拟机栈(线程私有)

是描述java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(stack frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每一个方法从调用直到执行完成的过程,就对应着一个栈帧在虚拟机中入栈到出栈的过程。

栈帧(frame)是用来存储数据和部分过程结构的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派(dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。

java核心知识点整理——JVM

 2.3本地方法区(线程私有)

本地方法区和Java Stack作用类似,区别是虚拟机栈为执行Java方法而服务,而本地方法栈为Native方法服务,如果一个VM实现使用C-linkage模型来支持Native调用,那么该栈将会是一个C栈,但HotSpotVM直接就把本地方法栈和虚拟机栈合二为一。

2.4堆(Heap-线程共享)-运行时数据区

是被线程共享的一块内存区域,创建的对象和数据都保存在java堆栈内存中,也是垃圾收集器进行垃圾收集的最重要的内存区域。由于现代 VM 采用分代收集算法, 因此 Java 堆从 GC 的角度还可以 细分为: 新生代(Eden 区From Survivor 区To Survivor 区)和老年代。