《深入Java虚拟机学习笔记》- 第5章 Java虚拟机
一、JVM的生命周期
- 当启动一个Java程序时,一个Java虚拟机实例就诞生了;当该程序关闭退出时,这个Java虚拟机也就随之消亡;
- JVM实例通过调用某个初始类的main方法来运行一个Java程序;这个main方法必须是public、static的,而且返回值必须是void;任何一个拥有这样的main方法的类都可以作为Java程序运行的起点;
- Java程序初始类中的main方法,将作为该程序初始线程的起点,其它任何线程都是由这个初始线程启动的;
- 守护线程和非守护线程
- 守护线程通常是由虚拟机自己使用的,比如执行垃圾收集任务的线程;
- Java程序可以把它任何创建的线程标记为守护线程;
- Java初始线程(即开始于main方法的线程)是非守护线程;
- 只要还有任何非守护线程在运行,那么这个Java程序也在运行,即这个JVM实例还存活着;当JVM中的所有非守护线程都终止时,JVM实例将自动退出;
二、JVM的体系结构
- JVM体系结构如图所示
- 方法区和堆是所有线程共享的;
- 当虚拟机装载一个class文件时,会从二进制数据中解析类型信息,然后把类型信息放到方法区中;
- 当程序运行时,虚拟机会把所有该程序在运行时创建的对象放在堆中;如下所示:
- 当每一个新线程被创建时,将得到自己的PC寄存器和Java栈;
如果线程正在执行的是一个Java方法,则PC寄存器的值总是指向下一条将被执行的指令;而它的Java栈则总是存储该线程中Java方法的调用状态(局部变量、参数、返回值以及中间结果);
如果线程正在执行的是本地方法,则是以依赖于具体实现的方式存储在本地方法栈、寄存器或是其它内存区中; - Java栈是由许多栈桢组成的,一个栈桢包含一个方法的调用状态;当线程调用一个Java方法时,虚拟机压入一个新的栈桢到该线程的Java栈中;当该方法返回时,这个栈桢将从Java栈中弹出;
- 数据类型
- Java 语言中的所有基本类型同样也都是Java虚拟机中的基本类型,但boolean有点特别,虽然Java虚拟机也把boolean当作基本类型,但是指令集 对boolean,只有很有限的支持:当编译器把Java源码编译为字节码时,它会用int或byte来表示boolean。在Java虚拟机 中,false是由整数零表示的,所有非零整数都表示true。涉及boolean的值的操作则会使用int。另外,boolean数据是当做byte数组来访问的,但是在堆区,它也可以被表示为位域;
- Java虚拟机中还有一个只在内部使用的基本类型:returnAddress,不能在程序开发时使用这个类型,它被用来实现Java程序中的finally子句;
- Java虚拟机有三种引用类型:
- 类类型:对类实例的引用;
- 接口类型:对实现了该接口的某个类实例的引用;
- 数组类型:对数组对象的引用;在Java虚拟机中,数组是个真正的对象;
- 装载、连接、初始化
- 装载:查找并装载类型的二进制数据;
- 连接:执行验证、准备以及解析,解析是可选的;
- 验证:确保被导入类型的正确性;
- 准备:为类变量分配内存,并初始化为默认值;
- 解析:把类型中的符号引用转换为直接引用;
- 初始化:把类变量初始化为正确的初始值;
- 方法区
- 当虚拟机装载某个类时,它使用类装载器定位相应的class文件,然后读入class文件中的线性二进制流,提取其中的类型信息,并将其存储到方法区;该类型中的类变量、静态变量也存储到方法区中;
- 所有线程共享方法区,因此它们对方法区数据的访问必须设计成线程安全的;
- 类型信息
- 全限定名;
- 直接超类的全限定名(如果这个类是Object类,则没有超类);
- 是类类型还是接口类型;
- 访问修饰符(public、abstract或final的某个子集);
- 任何直接接口的全限定名的有限列表;
- 该类型的常量池;
- 字段信息;
- 方法信息;
- 除常量以外的所有类变量、静态变量;
- 一个到类ClassLoader的引用;
- 一个到Class类的引用;
- 常量池:该类型所用常量的一个有序集合,包括直接常量和对其它类型、字段和方法的符号引用;
- 字段信息:类型的字段,包括声明顺序都要在方法区中保存,如字段名、字段的类型以及字段的修饰符;
- 方法信息:类型的方法,包括声明顺序都要在方法区中保存,如方法名、返回类型、参数数量,类型,顺序以及方法的修饰符;
- 如果不是本地方法和抽象方法,还要保存方法的字节码、操作数栈和方法的栈桢中局部变量的大小以及异常表;
- 类(静态)变量:类变量由所有类实例共享,即使没有任何类实例,它也可以被访问,因此它们总是作为类型信息的一部分保存到方法区中;
- 指向ClassLoader类的引用:每个类被装载的时候,虚拟机必须跟踪它是由启动类装载器还是由用户自定义类装载器装载的。如果是用户自定义类装载器,则虚拟机必须在类型信息中保存对该类装载器的引用;
- 虚拟机在动态连接期间使用这个信息,当某个类引用另一个类型时,虚拟机会请求装载发起引用类型的类装载器来装载被引用的类型;
- 这个动态连接的过程,对于虚拟机分离命名空间也很重要;
- 指向Class类的引用:虚拟机会为每个被装载的类型创建一个Class类的实例,并把这个实例的引用存储在方法区中;
- 有两个方法得到类型的Class对象引用: 方法 说明 备注
Class.forName(String className) 装载并返回该类型的Class对象引用 如果不能装载类型,则抛出ClassNotFoundException obj.getClass() 直接通过实例得到类型的Class对象引用 - 通过类型的Class对象引用,可以访问方法区中的类型信息: 方法 说明 备注
getName() 返回类型的全限定名 getSuperClass() 得到直接超类 如果是Object类型或是一个接口,则返回null isInterface() 判断是否是接口 如果是返回true,否则返回false getInterfaces() 得到所有直接接口的数组 如果没有实现任何接口,返回长度为0的数组 getClassLoader() 得到装载该类型的类装载器 如果类型是由启动类装载器装载的,则返回null
- 有两个方法得到类型的Class对象引用: 方法 说明 备注
- 方法表:为了提高访问效率,虚拟机实现中可能还包含其它数据结构来加快对原始数据的访问速度,如方法表;
- 虚拟机会为每个装载的非抽象类生成一个方法表,并把它作为类型信息的一部分保存在方法区中;
- 方法表是一个数组,其元素是所有它的实例可能调用的实例方法的直接引用,包括那些从超类继承过来的方法;
- 程序计数器:每一个线程都有自己的PC寄存器,它是在线程启动时创建的;PC寄存器大小是一个字长,因此即可以持有一个本地指针,也可以持有一个returnAddress;
- Java栈:每当启动一个新线程,虚拟机都会为它创建一个Java栈;
- Java栈以桢为单位保存线程的运行状态;
- 当线程调用一个Java方法时,虚拟机都会在线程的Java栈中压入一个新桢,在执行这个方法时,虚拟机使用这个栈桢存储参数、局部变量和中间运算结果等;
- Java方法可以以两种方法完成:一种是通过return正常返回;另一种是抛出异常中止;不管是哪种返回,虚拟机都会弹出当前栈桢,丢弃;
《深入Java虚拟机学习笔记》- 第5章 Java虚拟机的更多相关文章
- java JDK8 学习笔记——第16章 整合数据库
第十六章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作,称为JDBC驱动程 ...
- 深入Java虚拟机读书笔记第五章Java虚拟机
Java虚拟机 Java虚拟机之所以被称之为是虚拟的,就是因为它仅仅是由一个规范来定义的抽象计算机.因此,要运行某个Java程序,首先需要一个符合该规范的具体实现. Java虚拟机的生命周期 一个运行 ...
- 深入理解Java虚拟机学习笔记(一)-----Java内存区域
一 概述 对于 Java 程序员来说,在虚拟机自动内存管理机制下,不再需要像C/C++程序开发程序员这样为内一个 new 操作去写对应的 delete/free 操作,不容易出现内存泄漏和内存溢出问题 ...
- java JDK8 学习笔记——第17章 反射与类加载器
第十七章 反射与类加载器 17.1 运用反射 反射:.class文档反映了类基本信息,从Class等API取得类信息的方式称为反射. 17.1.1 Class与.class文档 1.java.lang ...
- 《深入理解Java虚拟机》笔记--第四章、虚拟机性能监控与故障处理工具
主要学习并记录在命令行中操作服务器时使用的六大命令工具,可视化工具JConsole和VisualVM在开发过程中熟悉. 一.jps:虚拟机进程状况工具(JVM Process Status Tool) ...
- java JDK8 学习笔记——第15章 通用API
第十五章 通用API 15.1 日志 15.1.1 日志API简介 1.java.util.logging包提供了日志功能相关类与接口,不必额外配置日志组件,就可在标准Java平台使用是其好处.使用日 ...
- java JDK8 学习笔记——第13章 时间与日期
第十三章 时间与日期 13.1 认识时间与日期 13.1.1 时间的度量 1.格林威治标准时间GMT 格林威治标准时间的正午是太阳抵达天空最高点之时.现在已经不作为标准时间使用. 2.世界时UT世界时 ...
- java JDK8 学习笔记——第11章 线程和并行API
第11章 线程与并行API 11.1 线程 11.1.1 线程 在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run( ...
- java JDK8 学习笔记——第18章 自定义泛型、枚举与注释
第十八章 自定义泛型.枚举与注释 18.1 自定义泛型 泛型定义: (1)仅定义在方法上的泛型语法 (2)用来限制泛型可用类型的extends与super关键字(3)?类型通配字符的使用 18.1.1 ...
- Java学习笔记整理第一章 java基本数据类型、修饰符、运算符
Java关键字: Java关键字是电脑语言里事先定义的,有特别意义的标识符,有时又叫保留字,还有特别意义的变量.Java的关键字对Java的编译器有特殊的意义,他们用来表示一种数据类型,或者表示程序的 ...
随机推荐
- Asp.net MVC 如何向webform一样在IIS里添加虚拟目录
相信很多用webform的程序猿都习惯性的使用虚拟目录的形式来对一个程序添加新的功能,那么在mvc下该如何来弄呢? 首先得有一个项目基层的项目,然后我们在这个项目的基础上新增一个功能模块,例如信息发布 ...
- js解决checkbox全选和反选的问题
function SelectAll() { var checkboxs=document.getElementsByName("chk_list"); for (var i=0; ...
- iOS socket编程 第三方库 AsyncSocket(GCDAsyncSocket)
Socket描述了一个IP.端口对.它简化了程序员的操作,知道对方的IP以及PORT就可以给对方发送消息,再由服务器端来处理发送的这些消息.所以,Socket一定包含了通信的双发,即客户端(Clien ...
- SpringMVC ResponseBody返回中文乱码解决方案
@RequestMapping(value = "/getForm") @ResponseBody public List<String> getForm(String ...
- WPF之小动画三
如果前两篇的博客太为普通,那么接下来的内容将让你动画实在是太厉害了.本文将会介绍两个关于纯手工实现动画的形式,当然动画效果就不用我多说了. 基于帧的动画: 此处的帧并不是之前介绍的Animation这 ...
- Python之数据结构篇
简介: 数据结构是可以处理一些数据的结构,或者说,他们是用来存储一组相关数据的.在python中有三种内建的数据结构,分别是列表.元组合字典.我们将会学习如何使用它们是编程变得简单. 列表 list是 ...
- linux进程模型总结
Linux进程通过一个task_struct结构体描述,在linux/sched.h中定义,通过理解该结构,可更清楚的理解linux进程模型. 包含进程所有信息的task_struct数据 ...
- lighttpd 介绍及安装
一,为什么要使用lighttpd? apache不可以吗? 在支持纯静态的对象时,比如图片,文件等 , lighttpd速度更快,更理想 (lighttp 图片处理好,nginx负载 ...
- 再谈 retain,copy,mutableCopy(官方SDK,声明NSString都用copy非retain)
之前一直以为retain就是简单的计数器+1,copy就是重新开辟内存复制对象: 其实不是这样,原来之前的自己独自徘徊于糊涂之中. (官方SDK,对NSString属性的定义都是用copy,而不是re ...
- python学习笔记四--元组
一.元组: 1. 不可变更的列表 2. 从语法上,她们是编写在小括号里,不是方括号里,列表是编写在方括号里的 3. 圆括号也同时用于表达式,如果想说明这是一个元组,不是表达式,可以在value后,关闭 ...