JVM的基本结构

首先,当一个程序启动之前,它的class会被类装载器装入方法区,执行引擎读取方法区的字节码自适应解析,边解析就边运行(其中一种方式),然后pc寄存器指向了main函数所在位置,虚拟机开始为main函数在java栈中预留一个栈帧(每个方法都对应一个栈帧),然后开始跑main函数,main函数里的代码被执行引擎映射成本地操作系统里相应的实现,然后调用本地方法接口,本地方法运行的时候,操纵系统会为本地方法分配本地方法栈,用来储存一些临时变量,然后运行本地方法,调用操作系统APIi等等。
为了消化上面的那个图,我们先来分析一下下面这张图。

为什么jvm的内存是分布在操作系统的堆中呢??
因为操作系统的栈是操作系统管理的,它随时会被回收,所以如果jvm放在栈中,那java的一个null对象就很难确定会被谁回收了,那gc的存在就一点意义都莫有了,而要对栈做到自动释放也是jvm需要考虑的,所以放在堆中就最合适不过了。
jvm的内存结构居然和操作系统的结构惊人的一致,区别在哪??
原来jvm的设计的模型其实就是操作系统的模型,基于操作系统的角度,jvm就是个java.exe/javaw.exe,也就是一个应用,而基于class文件来说,jvm就是个操作系统,而jvm的方法区,也就相当于操作系统的硬盘区,我为什么喜欢叫他permanent区吗,因为这个单词是永久的意思,也就是永久区,我们的磁盘就是不断电的永久区嘛,是一样的意思啊。而java栈和操作系统栈是一致的,无论是生长方向还是管理的方式,至于堆嘛,虽然概念上一致目标也一致,分配内存的方式也一直(new,或者malloc等等),但是由于他们的管理方式不同,jvm是gc回收,而操作系统是程序员手动释放,所以在算法上有很多的差异,gc的回收算法,估计是jvm里面的经典啊。
pc寄存器是干嘛用的??
所谓pc寄存器,无论是在虚拟机中还是在我们虚拟机所寄宿的操作系统中功能目的是一致的,计算机上的pc寄存器是计算机上的硬件,本来就是属于计算机,(这一点对于学过汇编的同学应该很容易理解,有很多的寄存器eax,esp之类的32位寄存器,jvm里的寄存器就相当于汇编里的esp寄存器),计算机用pc寄存器来存放“伪指令”或地址,而相对于虚拟机,pc寄存器它表现为一块内存(一个字长,虚拟机要求字长最小为32位),虚拟机的pc寄存器的功能也是存放伪指令,更确切的说存放的是将要执行指令的地址,它甚至可以是操作系统指令的本地地址,当虚拟机正在执行的方法是一个本地方法的时候,jvm的pc寄存器存储的值是undefined,所以你现在应该很明确的知道,虚拟机的pc寄存器是用于存放下一条将要执行的指令的地址(字节码流)。
对于一个运行中的Java程序而言,其中的每一个线程都有它自己的PC(程序计数器)寄存器,它是在该线程启动时创建的,PC寄存器的大小是一个字长,因此它既能够持有一个本地指针,也能够持有一个returnAddress(finally块)。当线程执行某个Java方法时,PC寄存器的内容总是下一条将被执行指令的“地址”,这里的“地址”可以是一个本地指针,也可以是在方法字节码中相对于该方法起始指令的偏移量。如果该线程正在执行一个本地方法,那么此时PC寄存器的值是“undefined”。
classLoader是如何加载class文件和存储文件信息??
当一个classLoder启动的时候,classLoader的生存地点在jvm中的堆,然后它会去主机硬盘上将A.class装载到jvm的方法区,方法区中的这个字节文件会被虚拟机拿来new A字节码(),然后在堆内存生成了一个A字节码的对象,然后A字节码这个内存文件有两个引用一个指向A的class对象,一个指向加载自己的classLoader。那么方法区中的字节码内存块,除了记录一个class自己的class对象引用和一个加载自己的ClassLoader引用之外,还记录了什么信息呢??见下图。

1.类信息:修饰符(public final)
是类还是接口(class,interface)
类的全限定名(Test/ClassStruct.class)
直接父类的全限定名(java/lang/Object.class)
直接父接口的权限定名数组(java/io/Serializable)
也就是 public final class ClassStruct extends Object implements Serializable这段描述的信息提取
2.字段信息:修饰符(pirvate)
字段类型(java/lang/String.class)
字段名(name)
也就是类似private String name;这段描述信息的提取
3.方法信息:修饰符(public static final)
方法返回值(java/lang/String.class)
方法名(getStatic_str)
参数需要用到的局部变量的大小还有操作数栈大小(操作数栈我们后面会讲)
方法体的字节码(就是花括号里的内容)
异常表(throws Exception)
也就是对方法public static final String getStatic_str ()throws Exception的字节码的提取
4.常量池:
4.1.直接常量:
1.1CONSTANT_INGETER_INFO整型直接常量池public final int CONST_INT=0;
1.2CONSTANT_String_info字符串直接常量池 public final String CONST_STR="CONST_STR";
1.3CONSTANT_DOUBLE_INFO浮点型直接常量池
等等各种基本数据类型基础常量池(待会我们会反编译一个类,来查看它的常量池等。)
4.2.方法名、方法描述符、类名、字段名,字段描述符的符号引用
也就是所有编译器能够被确定,能够被快速查找的内容都存放在这里,它像数组一样通过索引访问,就是专门用来做查找的。
编译时就能确定数值的常量类型都会复制它的所有常量到自己的常量池中,或者嵌入到它的字节码流中。作为常量池或者字节码流的一部分,编译时常量保存在方法区中,就和一般的类变量一样。但是当一般的类变量作为他们的类型的一部分数据而保存的时候,编译时常量作为使用它们的类型的一部分而保存
5.类变量:
就是静态字段( public static String static_str="static_str";)
虚拟机在使用某个类之前,必须在方法区为这些类变量分配空间。
6.一个到classLoader的引用,通过this.getClass().getClassLoader()来取得为什么要先经过class呢?思考一下,看一下上面的图,再回来思考。(class A 对象拥有A字节码和加载它的加载器地址引用)
7.一个到class对象的引用,这个对象存储了所有这个字节码内存块的相关信息。所有你能够看到的区域,比如:类信息,你可以通过this.getClass().getName()取得
所有的方法信息,可以通过this.getClass().getDeclaredMethods(),字段信息可以通过this.getClass().getDeclaredFields(),等等,所有在字节码中你想得到的,调用的,通过class这个引用基本都能够帮你完成。因为他就是字节码在内存块在堆中的一个对象
8.方法表,如果学习c++的人应该都知道c++的对象内存模型有一个叫虚表的东西,java本来的名字就叫c++- -,它的方法表其实说白了就是c++的虚表,它的内容就是这个类的所有实例可能被调用的所有实例方法的直接引用。也是为了动态绑定的快速定位而做的一个类似缓存的查找表,它以数组的形式存在于内存中。不过这个表不是必须存在的,取决于虚拟机的设计者,以及运行虚拟机的机器是否有足够的内存。
JVM的基本结构的更多相关文章
- 巩固java(二)----JVM堆内存结构及垃圾回收机制
前言: 我们在运行程序时,有时会碰到内存溢出(OutOfMemoryError)的问题,为了解决这种问题,我们有必要了解JVM的内存结构和垃圾回收机制. 正文: 1.JVM堆内存结构 ...
- 了解java虚拟机---JVM的基本结构(1)
1. JVM的基本结构 1.1. 类加载子系统 类加载子系统负责从文件或者网络中加载Class信息,加载的类信息存放于方法区的内存空间.方法区中可能还会存放运行时常量信息,包括字符串与数字常量.(这部 ...
- JVM的内存结构,JVM的回收机制
内存作为系统中重要的资源,对于系统稳定运行和高效运行起到了关键的作用,Java和C之类的语言不同,不需要开发人员来分配内存和回收内存,而是由JVM来管理对象内存的分配以及对象内存的回收(又称为垃圾回收 ...
- 概览JVM的基本结构和JVM内存结构
概览JVM的基本结构和JVM的内存结构 这里概要介绍一下JVM在启动后,作为操作系统的一个进程的基本结构,以及从操作系统角度看,JVM如何管理它从操作系统里申请来的内存的,也就是JVM的内存结构或者叫 ...
- JVM 垃圾回收机制和常见算法和 JVM 的内存结构和内存分配(面试题)
一.JVM 垃圾回收机制和常见算法 Sun 公司只定义了垃圾回收机制规则而不局限于其实现算法,因此不同厂商生产的虚拟机采用的算法也不尽相同.GC(Garbage Collector)在回收对象前首先必 ...
- JVM之内存结构详解
对于开发人员来说,如果不了解Java的JVM,那真的是很难写得一手好代码,很难查得一手好bug.同时,JVM也是面试环节的中重灾区.今天开始,<JVM详解>系列开启,带大家深入了解JVM相 ...
- JVM的内存结构以及性能调优
JVM的内存结构以及性能调优 发布时间: 2017-11-22 阅读数: 16675 JVM的内存结构以及性能调优1:JVM的结构主要包括三部分,堆,栈,非堆内存(方法区,驻留字符串)堆上面存储的是引 ...
- JVM的基本结构和JVM的内存结构
这里概要介绍一下JVM在启动后,作为操作系统的一个进程的基本结构,以及从操作系统角度看,JVM如何管理它从操作系统里申请来的内存的,也就是JVM的内存结构或者叫JVM内存模型. 1.JVM的基本结构 ...
- JVM:内存结构
JVM:内存结构 说明:这是看了 bilibili 上 黑马程序员 的课程 JVM完整教程 后做的笔记 内容 程序计数器 虚拟机栈 本地方法栈 堆 方法区 直接内存 1. 程序计数器 1.1 定义 P ...
随机推荐
- vmware, failed to lock the file
电脑死机,进不了桌面,实在不行就重启,但是在运行着虚拟机,重启后打开VMware虚拟机,提示failed to lock the file,进不去了,急阿,里面不少资料呢...问万能的Google,终 ...
- 关闭火车头dedecms发布模块自动关键词,解决火车头发布dedecms文章关键词过多问题
用火车头发布dedecms文章时,经常会自动添加关键词,这些关键词默认有10个,数量过多,而且是随机提取的,乱七八糟的词都进去了,如下图所示: 这些关键词可能会成为se判断你作弊的依据,现在se也弱化 ...
- Forth scrum meeting - 2015/10/29
今天下午,我们终于要到了MOOC服务器端开发人员的联系方式,于是我们小组派了三名同学去实验室与他们进行了交流,并咨询了他们一些关于API接口的问题.他们也对我们这个客户端的开发提出了一些建议. 开发团 ...
- Linux的防火墙--IP Tables
导读 IP Table已经集成在Linux 2.4及以上版本的内核中,同Windows下的众多“傻瓜”防火墙不同的是,IP Table需要用户自己定制相关规则.下面我就给大家简单介绍一下关于防火墙的基 ...
- lvs之nat技术的学习与实践
lvs nat 服务器搭建 1.配置三个虚拟机.一台用于做lvs 两台用于做web server 进行测试 (lvs服务器要配备两块网卡); lvs 服务器 两块网卡 分别为vmnet1 vm ...
- 面向侧面的程序设计AOP-------《三》.Net平台AOP技术概览
本文转载自张逸:晴窗笔记 .Net平台与Java平台相比,由于它至今在服务端仍不具备与unix系统的兼容性,也不具备类似于Java平台下J2EE这样的企业级容器,使得.Net平台在大型的企业级应用上, ...
- 【转】maven导出项目依赖的jar包
本文转自:http://my.oschina.net/cloudcoder/blog/212648 一.导出到默认目录 targed/dependency 从Maven项目中导出项目依赖的jar包:进 ...
- Android dp px转化公式
// DisplayMetrics metrics = getResources().getDisplayMetrics(); // int statusBarHeight = (int) Math. ...
- Enum:Smallest Difference(POJ 2718)
最小的差别 题目大意:输入一串数字,问你数字的组合方式,你可以随意用这些数字组合(无重复)来组合成一些整数(第一位不能为0),然后问你组合出来的整数的差最小是多少? 这一题可以用枚举的方法去做,这里我 ...
- Unsupported major.minor version 51.0 在配置/运行Maven工程时,JDK与Maven所引用的jdk版本不一致
在配置Maven工程,部署到tomcat服务器运行的过程中,遇到如下错误: "Unsupported major.minor version 51.0 " 错误原因是由于maven ...