了解java虚拟机---JVM的基本结构(1)

1. JVM的基本结构

1.1. 类加载子系统

类加载子系统负责从文件或者网络中加载Class信息,加载的类信息存放于方法区的内存空间。方法区中可能还会存放运行时常量信息,包括字符串与数字常量。(这部分常量信息是Class文件中常量池部分的内存映射)。

1.2. JAVA堆

JAVA的堆在JVM启动的时候建立,几乎所有的Java对象实例都存放于Java堆中。堆空间是所有线程共享的。根据垃圾回收机制的不同,JAVA堆有可能拥有不同的结构。最为常见的一种结构是将整个堆分为新生代和老年代以及持久代。

1. 对象的分配

对象首先分配在eden区,在一次Young GC后,如果对象还存活则会进入S0(from)或者S1(to).之后每次Young GC后如果对象存活,它的年龄就会加1,当对象年龄达到一定条件后,就会被认定为是老年对象,从而进入老年代。

package com.hl.heap;

public class SimleHeap {
	public int id;

	public SimleHeap(int id) {
		this.id = id;
	}

	public void show(){
		System.out.println("My ID is " + id);
	}

	public static void main(String[] args) {
		SimleHeap s1 = new SimleHeap(1);
		SimleHeap s2 = new SimleHeap(2);
		s1.show();
		s2.show();
	}
}

SimpleHeap类的信息存放在方法区,主函数中的s1和s2存放在JAVA栈中,并且指向堆中的两个实例。

1.3. 直接内存

JAVA的NIO允许java程序使用直接内存,直接内存是在JAVA堆外的,直接向系统申请的内存空间。通常访问直接内存的速度要优于JAVA堆,直接内存适用于频繁读写的场景,直接内存在JAVA堆外,因此它的大小不会直接受限于Xmx指定的最大堆大小的限制,但是JAVA堆和直接内存依然受限于系统的最大内存。

1.4. 垃圾回收系统

垃圾回收器可对方法区、JAVA堆和直接内存进行回收。

1.5. JAVA栈

每个JVM线程都有一个私有的JAVA栈,JAVA栈在线程创建的时候创建。JAVA栈中保存着局部变量、方法参数、同时和JAVA方法的调用、返回密切相关。

1.5.1 函数调用-出入JAVA栈

栈是线程私有的内存空间,线程执行的基本行为是函数调用,每次函数调用的数据都是通过JAVA栈传递的。JAVA栈是一块先进后出的数据结构,只支持出栈入栈两种操作。在JAVA栈中保存的主要内容为栈帧。每一次函数调用,都会有一个对应的栈帧被压入JAVA栈,每一个函数调用结束,都会有一个栈帧被弹出JAVA栈。JAVA方法有两种返回函数的方式,一种是正常的return,一个是抛出异常,不管哪种方式,都会导致栈被弹出。在一个栈中,至少要包含局部变量表、操作数栈和帧数据区几个部分。JVM提供了-Xss指定线程栈的最大空间,这个参数决定了函数调用的最大深度。

JAVA栈的结构

1.5.1.1 局部变量表

它用于保存函数的参数以及局部变量,局部变量表中的变量只在当前函数调用中有效,当函数调用结束后,随着函数栈帧的销毁,局部变量表也会随之销毁。由于局部变量表在栈帧中,如果函数的参数与局部变量较多,会使得局部变量表膨胀,从而每一次函数调用就会占用更多的栈空间,最终导致函数的嵌套调用次数减少。

1.5.1.2 操作数栈

主要用于保存计算过程中的中间结果,同时作为计算过程中变量的临时存储空间。操作数栈也是一个先进后出的数据结构,只支持入栈和出栈两种操作。

1.5.1.3 帧数据区

帧数据区中保存着返回常量池的指针,方便程序访问常量池。当函数返回或者出现异常时,虚拟机必须恢复调用者函数的栈帧,并让调用者函数继续执行下去,虚拟机必须有一个异常处理表,方便在发生异常时找到处理异常的代码,因此异常处理表也是帧数据区中重要的一部分。

1.5.1.4 栈上分配

是JVM优化的一项技术,对于哪些线程的私有对象,可以将它们打散分配在栈上,而不是分配在堆上。当函数调用结束后可以自行销毁,不需要GC介入,从而提高系统性能。

1.6. 方法区

和JAVA堆一样,方法区是一块所有线程共享的内存区域。它用于保存系统的类信息,比如类的字段、方法、常量池等,方法区的大小决定了系统可以保存多少个类。在JDK1.7中方法区可以理解为永久区在JDK1.8中永久区被彻底移除,取而代之的是元数据区,元数据区是一块堆外的内存,与持久区不同的是,如果不指定元数据区大小,虚拟机会消耗系统内存,直到耗尽为止。

1.7. 本地方法栈

本地方法栈和java栈非常类似,最大的不同在于java栈用于java方法的调用,而本地方法栈则用于调用本地方法(dll,so)。

1.8. PC(Program Counter)寄存器

也是每个线程私有空间,Java虚拟机会为每个Java线程创建PC寄存器。在任意时刻,一个Java线程总是在执行一个方法,这个正在被执行的方法称为当前方法。如果当前方法不是本地方法,PC寄存器就会指向当前正在被执行的指令。如果当前方法是本地方法,那么PC寄存器的值就是undefined。

1.9. 执行引擎

负责执行虚拟机的字节码

?版权声明:本文为【翰林小院】(huhanlin.com)原创文章,转载时请注明出处!

原文地址:https://www.cnblogs.com/hanlinhu/p/9486284.html

时间: 2024-11-02 10:33:32

了解java虚拟机---JVM的基本结构(1)的相关文章

Java虚拟机JVM学习05 类加载器的父委托机制

Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap) 扩展类加载器(Extension) 系统类加载器(System) 2.用户自定义的类加载器: java.lang.ClassLoader的子类,用户可以定制类的加载方式. JVM自带的加载器 Java虚拟机自带了以下几种加载器. 1.根(Bootstrap)类加载器: 该加载器没有父加载器. 它

深入Java虚拟机JVM类加载初始化学习笔记

1. Classloader的作用,概括来说就是将编译后的class装载.加载到机器内存中,为了以后的程序的执行提供前提条件. 2. 一段程序引发的思考: 风中叶老师在他的视频中给了我们一段程序,号称是世界上所有的Java程序员都会犯的错误. 一般不假思索的结论就是,a=1,b=1.给出的原因是:a.b都是静态变量,在构造函数调用的时候已经对a和b都加1了.答案就都是1.但是运行完后答案却是a=1,b=0. 为什么呢,这3句无非就是静态变量的声明.初始化,值的变化和声明的顺序还有关系吗?Java

书籍推荐:《实战Java虚拟机——JVM故障诊断与性能优化》下载

本书详细介绍Java虚拟机的基本原理和优化诊断方法.其中重点介绍Java虚拟机的体系结构.常用的虚拟机参数.Java虚拟机的垃圾回收原理.算法以及目前虚拟机所支持的各种垃圾回收器及其区别.特点和使用方法.在实践和调优方面,重点介绍了Java的堆.栈分析方法,性能调优的一般思路.手段和工具.此外,还详细介绍了虚拟机内有关"锁"的实现以及优化方法. 作为对虚拟机的深入了解,本书还将详细介绍Java类的基本格式.装载过程和虚拟机的执行机制. Java虚拟机目前是Java.Scala.Cloj

Java虚拟机JVM简单理解

Java虚拟机JVM的作用: Java源文件(.java)通过编译器编译成.class文件,.class文件通过JVM中的解释器解释成特定机器上的机器代码,从而实现Java语言的跨平台. JVM的体系结构包含三个主要的子系统和一个内存区,分别是: 垃圾回收器:用于回收堆(heap)中无引用的对象. 类装载子系统:定位及导入二进制class文件,校验被导入类的正确性,为类变量分配初始化内存,以及帮助解析符号引用. 执行引擎:执行被转载类中的方法指令. 运行时数据区:又叫做虚拟机内存或Java内存.

《深入理解Java虚拟机 JVM高级特性...》核心笔记

深入理解Java虚拟机 JVM高级特性与最佳实践(第二版) 核心笔记 JAVA 环境: JAVA虚拟机高级特性: 一:java内存区域与内存异常 一):运行数据区     1:程序计数器(Program Counter Register),也称"PC寄存器" A:用来指示需要执行哪条指令的.(在汇编语言中,CPU在得到指令之后,程序计数器便自动加1或者根据                    转移指针得到下一条指令的地址,如此循环,直至执行完所有的指令.) B:由于在JVM中,多线程

java虚拟机--JVM

java虚拟机 是安装在计算机操作系统上的一个虚拟计算机. 专门用于处理java程序和底层操作系统的链接工作,将java程序翻译成底层的操作系统可以理解的语言. 有别于JDK.JDK是java的开发环境,是java开发人员需要的,里面除了JVM,还有一些其他的东西.JVM是小于JDK的. JVM的结构图如下图所示: 1. 类加载器:加载类文件到内存.[这里的类文件是class文件] 2. 运行数据区:1中加载的class文件,全部保存在运行数据区.java能够很好的运行,也是得益于运行数据区的管

Java虚拟机JVM学习04 类的初始化

Java虚拟机JVM学习04 类的初始化 类的初始化 在初始化阶段,Java虚拟机执行类的初始化语句,为类的静态变量赋予初始值. 在程序中,静态变量的初始化有两种途径: 1.在静态变量的声明处进行初始化: 2.在静态代码块中进行初始化. 没有经过显式初始化的静态变量将原有的值. 静态变量的声明语句,以及静态代码块都被看做类的初始化语句,Java虚拟机会按照初始化语句在类文件中的先后顺序来依次执行它们. 类的初始化步骤 1.假如这个类还没有被加载和连接,那就先进行加载和连接. 2.假如类存在直接的

java虚拟机jvm启动后java代码层面发生了什么?

java虚拟机jvm启动后java代码层面发生了什么? 0000 我想验证的事情 java代码在被编译后可以被jdk提供的java命令进行加载和运行, 在我们的程序被运行起来的时候,都发生了什么事情, 下面就来探究下这个问题, 这个问题被拆成了两个问题, 第一个问题用来确定发生了哪些事情, 第二个问题用来确定这些事情是如何进行的. java进程里面都发生了哪些活动? 这些活动在java代码(反编译或者是源码)级别有所体现吗? 0001 寻找验证的方式 当我在探究上面两个问题时, 我想了很多方式去

JAVA虚拟机(JVM)以及跨平台原理(JDK、JRE、JVM)

相信大家已经了解到Java具有跨平台的特性,可以“一次编译,到处运行”,在Windows下编写的程序,无需任何修改就可以在Linux下运行,这是C和C++很难做到的. 那么,跨平台是怎样实现的呢?这就要谈及Java虚拟机(Java Virtual Machine,简称 JVM). JVM也是一个软件,不同的平台有不同的版本.我们编写的Java源码,编译后会生成一种 .class 文件,称为字节码文件.Java虚拟机就是负责将字节码文件翻译成特定平台下的机器码然后运行.也就是说,只要在不同平台上安