JVM体系结构--方法区
2015-12-21 17:31
141 查看
JVM由一个类装载子系统,执行引擎,运行时数据区和本地方法接口组成。
主要分类:启动类装载器,系统类装载器和用户自定义装载器
启动类装载器只在系统类的安装目录中查找,系统内装载器在CLASSPATH包含的子目录中查找,这两种类装载器主要负责类型的装载,用户自定义类装载器就是java程序的一部分,通过defineClass,findSystemClass,resolveClass与JVM相连
主要分类:方法区,堆,程序计数器,java栈,本地方法栈
方法区
最核心的功能?
用来储存装载类型的信息。
如何获取装载类型的信息?
当虚拟机装载某个类型时,使用类装载器搜索到某个class文件,也就是二进制数据流,传输到虚拟机中,提取类型信息到方法区。
如何储存?
选择合理的数据结构,由设计者决定
类型信息的内容?
基本信息:类/超类全限定名或者超接口全限定名的有序列表,类类型或接口类型,访问修饰符
扩展信息:常量池,字段信息,方法信息,类(静态)变量,指向ClassLoader类的引用,指向Class类的引用
常量池
直接常量+对其它类型,字段或方法的引用。通过索引访问
字段信息
字段名,字段类型,字段修饰符
方法信息
方法名,返回类型,参数,修饰符
类(静态)变量
编译时常量:final声明或初始化的类变量。一般的类变量作为声明它们类型的一部分数据而保存,编译时常量作为使用它们类型的一部分而保存
指向ClassLoader类的引用
类型装载时,确定是哪种类装载器装载的
指向Class类的引用
关联Class对象实例和数据类型信息。通过forName方法或getClass方法获取该引用,没有则抛出ClassNotFoundException异常。
方法区示例
运行该test程序,虚拟机找到并读入相应的class文件”Test.class”,从该二进制数据流中提取类型信息并放到方法区。通过保存在方法区的字节码,执行main方法,虽然Demo还没有被装载,但此时Test的常量池中有一个”Demo”的符号引用,通过搜索(散列表,搜索树等),forName,getClass等方式找到Demo类的引用,若虚拟机还没有装载Demo类,通过类装载子系统来进行类型信息的获取,并保存到方法区,将该引用替换Test常量池中的第一项,之后就可以快速访问Demo类了,替换的过程叫做常量池的解析。虚拟机并不是把程序中用到的所有类都装载才开始运行程序,而是只有在需要时才装载相应的类,这也是动态的一种体现吧。虚拟机为Demo对象分配内存(虚拟机能够根据方法区的类型信息来确实对象的内存大小),并把Demo对象压栈,完成了main指令。
类装载子系统
主要职责:根据全限定名来装载类型(同一限定名通过命名空间区分)。主要分类:启动类装载器,系统类装载器和用户自定义装载器
启动类装载器只在系统类的安装目录中查找,系统内装载器在CLASSPATH包含的子目录中查找,这两种类装载器主要负责类型的装载,用户自定义类装载器就是java程序的一部分,通过defineClass,findSystemClass,resolveClass与JVM相连
执行引擎
主要职责:负责执行包含在装载类的方法中的指令。运行时数据区
主要职责:JVM运行一个程序时,用来储存许多东西。主要分类:方法区,堆,程序计数器,java栈,本地方法栈
方法区
最核心的功能?
用来储存装载类型的信息。
如何获取装载类型的信息?
当虚拟机装载某个类型时,使用类装载器搜索到某个class文件,也就是二进制数据流,传输到虚拟机中,提取类型信息到方法区。
如何储存?
选择合理的数据结构,由设计者决定
类型信息的内容?
基本信息:类/超类全限定名或者超接口全限定名的有序列表,类类型或接口类型,访问修饰符
扩展信息:常量池,字段信息,方法信息,类(静态)变量,指向ClassLoader类的引用,指向Class类的引用
常量池
直接常量+对其它类型,字段或方法的引用。通过索引访问
字段信息
字段名,字段类型,字段修饰符
方法信息
方法名,返回类型,参数,修饰符
类(静态)变量
编译时常量:final声明或初始化的类变量。一般的类变量作为声明它们类型的一部分数据而保存,编译时常量作为使用它们类型的一部分而保存
指向ClassLoader类的引用
类型装载时,确定是哪种类装载器装载的
指向Class类的引用
关联Class对象实例和数据类型信息。通过forName方法或getClass方法获取该引用,没有则抛出ClassNotFoundException异常。
方法区示例
class Test{ public static void main(String args[]){ Demo demo = new Demo(); demo.aa(); } } class Demo{ void aa(); }
运行该test程序,虚拟机找到并读入相应的class文件”Test.class”,从该二进制数据流中提取类型信息并放到方法区。通过保存在方法区的字节码,执行main方法,虽然Demo还没有被装载,但此时Test的常量池中有一个”Demo”的符号引用,通过搜索(散列表,搜索树等),forName,getClass等方式找到Demo类的引用,若虚拟机还没有装载Demo类,通过类装载子系统来进行类型信息的获取,并保存到方法区,将该引用替换Test常量池中的第一项,之后就可以快速访问Demo类了,替换的过程叫做常量池的解析。虚拟机并不是把程序中用到的所有类都装载才开始运行程序,而是只有在需要时才装载相应的类,这也是动态的一种体现吧。虚拟机为Demo对象分配内存(虚拟机能够根据方法区的类型信息来确实对象的内存大小),并把Demo对象压栈,完成了main指令。
相关文章推荐
- tomcat 404
- 关于 intent 的各种解释
- 数据库操作
- NSRunLoop
- 【C51】单片机定时器介绍
- 使用WebView实现文件下载的两种方式
- JAVA中List转换String,String转换List,Map转换S
- 代码重构
- jsp学习
- 登录sqlplus 后,显示问号 ????
- Oozie配置数据库
- Java面向对象编程-第9章学习笔记
- WiFi认证弹出页
- 终生好习惯:早上白开水一杯——年轻漂亮一辈子
- 解决:Could not find debuginfo pkg for dependency package glibc-2.12-1.132.el6_5.3.i686
- Android开发案例 - 淘宝商品详情
- MySQL创建数据库和表的Demo
- eclipse代码中每行的开始和结尾出现多余的特殊符号
- JS日期时间类型(Y-m-d H:i:s)与时间戳互转
- Oozie MapReduce Action配置的要点