[看书笔记]《深入java虚拟机》——java体系结构(二)

java虚拟机的三种含义:
- 抽象的规范
- 一个具体的实现
- 一个运行中的虚拟机实例

---------------------java虚拟机的生命周期:
java虚拟机实例的天职就是负责运行一个java程序。
启动一个java程序,一个虚拟机实例诞生了;程序关闭退出,虚拟机消亡。
有几个java程序正在运行,就有几个java虚拟机实例。每个java程序都运行在自己的java虚拟机实例中。

java虚拟机中有两种线程:
- 守护线程:由虚拟机自己使用的(执行垃圾收集线程),java程序也可以把任何线程标记为守护线程。
- 非守护线程:main()这种。

非守护线程都终止时,虚拟机实例才自动退出。(也可以调用Runtime或System的exit()方法退出程序)。

---------------------java虚拟机的体系结构:
见同目录第五章.Java虚拟机-体系结构图!
方法区和堆是该虚拟机实例的所有线程共享的。
当虚拟机装载一个class文件时,他会从这个class文件包含的二进制数据中解析类型信息,然后把这些类型信息放到方法区中。
当程序运行时,虚拟机会把所有该程序在运行时创建的对象都放到堆中。

每个新线程被创建时,他都将得到它自己的PC寄存器以及一个java栈(不是所有线程共享)。
java虚拟机为每个线程创建内存区,这些内存区域是私有的,任何线程都不能访问另一个线程的PC寄存器或者java栈。
如果线程正在执行的是一个java方法(非本地方法),那么PC寄存器的值将总是指示下一条将被执行的指令。
java栈则总是存储该线程中java方法调用的状态(局部变量、被调用时传进来的参数、返回值、运算的中间结果)

本地方法调用的状态则是以某种依赖于具体实现的方式存储在本地方法栈中,也可能在寄存器或者其他某些特定实现相关的内存区中。

---------------------栈帧(1):
java栈上由许多栈帧(帧)组成的,一个栈帧包含一个java方法调用的状态。
当线程调用一个java方法时,虚拟机压入一个新的栈帧到该线程的java栈中;当方法返回时,这个栈帧被从java栈中弹出并抛弃。

java虚拟机没有寄存器,其指令集使用java栈来存储中间数据(为了平台无关性)。

---------------------类型数据
类型数据分为来那个中:
基本类型:float、double、byte、short、int、long、char、boolean
引用类型:reference(类引用、接口引用、数组引用)
注意:编译成字节码时boolean用int表示,

java虚拟机中,最基本的数据单元就是字,至少选择32位作为字长。
运行时数据区的大部分内容,都是基于“字”这个抽象概念的。

---------------------类装载器子系统:
类装载器的装载、连接和初始化:
- 装载:查找并装载类型的二进制数据
- 连接:执行验证,准备,以及解析(可选)。
验证:确保被导入类型的正确性。
准备:为静态变量分配内存,并将其初始化为默认值。
解析:把类型中的符号引用转换为直接引用。
- 初始化:把静态变量初始化为正确初始值。

启动类装载器:
只要是符合java class文件格式的二进制文件,java虚拟机实现都必须能够从中辨别并装载器中的类和接口。每个java虚拟机实现必须有一个启动类加载器来加载受信任的类,比如java API。

用户自定义类装载器:
用户自定义的类装载器是普通的java对象,它的类必须派生自java.lang.ClassLoader类。ClassLoader类中定义的方法为程序提供了访问类装载器机制的接口。
用户自定义类装载器和Class类的实例都放在内存中的堆区,而装载的类型信息则都位于方法区。

ClassLoader类的四个通往java虚拟机的方法:
protected final Class defineClass(String name, byte data[], int offset, int length);
接收一个名为data[]的字节数组,并且在data[offset]到data[data+length]之间的二进制数据必须符合java class格式(表示一个新的可用类),name是该类型的全限定名,并将赋以默认的保护域。注意:该方法返回Class对象实例时表示指定的class文件已经被找到并装载到了方法区(不一定连接和初始化)

protected final Class defineClass(String name, byte data[], int offset, int length, 
ProtectionDomain protectionDomain);
与前面一样,只是,该类型的保护域将由它的protectionDomain参数指定。

protected final Class findSystemClass(String name);
接收一个字符串name(该类型的全限定名),用于启动系统类装载器(必须保证能启动)。

protected final void resolveClass(Class c);
接收一个Class实例的引用作为参数,它将对该Class实例表示的类型执行连接动作(必须保证能执行连接动作)。

---------------------方法区:
所有线程都共享方法区,所以它们对方法区数据的访问必须被设计为是线程安全的。
方法区的大小不必说固定的,虚拟机可以根据应用的需要动态调整。
方法区不必是连续的。
方法区也可以被垃圾收集。

类型信息:
对每个装载的类型,虚拟机都会在方法区中存储一下类型信息:
- 该类型全限定名
- 该类型的直接超类的全限定名(除非是Object类,没有超类)
- 该类型是类类型还是接口类型
- 该类型的访问修饰符(public、abstract、final的某个子集)
- 任何型直接超接口的全限定名的有序列表

- 该类型的常量池【核心】:所有常量的类型字段方法的符号引用(索引访问)
- 字段信息:字段名,字段类型,字段修饰符
- 方法信息:方法名,返回类型,参数数量和类型(按序),方法修饰符
- 除了常量以外的静态变量
- 一个到类ClassLoader的引用:跟踪保存该类加载时所用的加载器的类别
- 一个到Class类的引用:虚拟机会创建一个相应的java.lang.Class类的实例

---------------------方法表:
方法表:类型数据结构
虚拟机为每个非抽象类都生成一个表,把它作为类信息的一部分保存在方法区。
方法表是一个数组,元素是所有它的实例可能被调用的实例方法的直接引用
,包括是超类直接继承过来的方法。运行时可以通过方法表快速搜寻在对象中调用的实例方法。

---------------------堆:
java程序在运行时创建的所有类实例或数组都放在同一个堆中(要考虑线程同步问题)。
和方法区一样,堆空间也不是连续的内存区。

---------------------数组:
数组的内部表示:
在java中,数组才是真正的对象
和其他对象一样,数组总是存储在堆中。
和其他对象一样,数组也有一个与他们的类关联的Class实例,所有具有相同维度和类型的数组都是同一个类的实例(不管数组的长度是多少)。

数组类的名称由两部分组成,每一维度用一个"["表示,用字符或字符串表示元素类型。如“[[Ljava/lang/Object”表示元素为Object的二维数组。

在堆中,每一个数组对象还必须要保存数组的长度、数组数据以及某些指向数组的类数据的引用。

---------------------程序计数器(PC寄存器):
每一个线程都有它自己的PC寄存器,它是在该线程启动的时候创建的。
PC寄存器的大小是字长,因此能够持有一个本地指针,也能够持有一个returnAddress。当线程执行某个java方法时,PC寄存器的内容总是写一条将被执行的指令的地址,这里的地址可以是个本地指针,也可以是在方法字节码中相对于该方法其实指令的偏移量。如果该线程正在执行一个本地方法,此时PC寄存器的值是“undefined”。

---------------------Java栈:
每当启动一个新线程时,java虚拟机都会为它分配一个java栈。
虚拟机智慧直接对java栈执行两种操作:以帧为单位的压栈或出栈。
每当线程调用一个java方法时,虚拟机都会在该java栈中压入一个新帧。
java方法不管是正常返回还是抛异常中止,虚拟机都会将当前栈弹出java栈,然后释放内存。

java栈和栈帧在内存中也不必说连续的。

---------------------栈帧(2):
栈帧的构成:
- 局部变量区:
是一个以字长为单位,从0开始计数的数组。字节码指令通过从0开始的索引来使用其中的数据。
int、float、reference和returnAddress的值在数组中只占一项;
byte、short、char的值在存入数组前都被转换成int,所以也只占一项;
boolean虚拟机不支持,用int来表示,所以也只占一项;
long、double的值在数组中占两项(使用只要指出第一项索引值)。
局部变量区包含对应的方法参数和局部变量。
按参数的顺序来存入局部变量数组中。真正的局部变量顺序任意。

- 操作数栈:
是一个以字节为单位的数组(不是通过索引来访问),是通过标准的栈操作(压栈和出栈)来访问。
存储的数据类型和局部变量区的一样。
虚拟机把操作数栈作为他的工作区,大多数指令都要从这里弹出数据,执行计算,然后把结果压回到操作数栈中。

- 帧数据区:
常量池解析、正常方法返回、异常派发机制。
每当虚拟机要执行某个需要用到常量池数据的指令时,它都会通过帧数据区中指向常量池的指针来访问它。
帧数据区还要帮助虚拟机处理java方法的正常结束或异常中止:
如果正常结束:虚拟机必须恢复发起调用的方法的(上一个)栈帧,调用完成方法的指令的下一个指令。如果有返回值,虚拟机将把返回值压倒发 起调用的方法的操作数栈。
如果抛出异常,根据帧数据区的异常表来处理。如果有catch语句,就会交给catch中的代码,如果没有,则立即异常中止。

---------------------本地方法栈:
当线程调用本地方法时,虚拟机会保持java栈不变,不再在线程的java栈中压入新的帧,虚拟机只是简单地动态连接并直接调用指定的本地方法。

就像其他运行时内存区一样,本地方法栈占用的内存区也不必说固定大小的,它可以根据需要动态扩展或者收缩。

---------------------执行引擎:
任何java虚拟机实现的核心都是它的执行引擎。
在java虚拟机规范中,执行引擎的行为使用指令集来定义。
作为运行时实例的执行引擎就是一个线程。
运行中java程序的每一个线程都是一个独立的虚拟机执行引擎的实例。从生命周期的开始到结束,它要么在执行字节码,要么在执行本地方法。

本文转自天天_byconan博客园博客,原文链接:http://www.cnblogs.com/tiantianbyconan/archive/2013/02/24/2923987.html,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540454.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全新的membership框架Asp.net Identity(1)——.Net membership的历史

在Asp.net上,微软的membershop框架经历了Asp.net membership到Asp.net simple membership,再到现在的Asp.net Identity. 每一次改变,都使得验证框架更加的适应变化和可定制。这篇文章是Asp.net Identity系列的开篇,主要就membersh…

二.编写第一个c#程序(注释,命名空间,类,Main方法,标识符,关键字,输入,输出语句,)...

复习编写一个控制台应用程序,目标是在控制台输出“Hello World” 1.第一步,打开Visual Studio 2012以上版本(我用的是VS 2015),打开完成后出现以下界面 2.第二步,这时候就要新建一个解决方案了,创建解决方案可以直接点…

node oauth2验证_如何设置和使用护照OAuth Facebook身份验证(第1部分)| Node.js

node oauth2验证In my last articles, we looked at the implementation of the passport-local authentication strategy. We also looked at the various requirements to get started with the login form. 在上一篇文章中,我们介绍了护照本地身份验证策略的实现…

RYU控制器安装`

2019独角兽企业重金招聘Python工程师标准>>> 同样是参考了http://linton.tw/2014/02/11/note-how-to-set-up-ryu-controller-with-gui-component/的内容。 1. 由于Ubuntu中自带有Python,因此直接开始安装pip apt-get install python-pip apt-get i…

数据库连接池的设计思路及java实现

2019独角兽企业重金招聘Python工程师标准>>> connectionPool.DBConnectionManager [java] view plain copy package connectionPool; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; i…

窄带物联网(NB-IoT)初步了解

哪有什么天生如此,只是我们天天坚持。既然总有人要赢的话,为什么不能是我呢?[TOC] 什么是NB-Iot? 基于蜂窝的窄带物联网(Narrow Band Internet of Things, NB-IoT)成为万物互联网络的一个重要分支。NB-IoT构建于蜂窝网…

JavaOne大事纪:IBM谈OpenJ9和Open Liberty

JavaOne大会以IBM陈述其最近对开源社区的贡献作为开场:OpenJ9、Open Liberty和MicroProfile。IBM杰出工程师John Duimovich做了“IBM和Java:助力下一代创新”的开场演讲。\\读者可以回看演讲视频。\\Duimovich说IBM之所以致力于推动Java生态系统的创新&a…

c语言格式对齐填充_C ++中类的大小 课堂上的填充和对齐| 派生类的大小

c语言格式对齐填充Prerequisite: 先决条件: sizeof() operator in C/C C / C 中的sizeof()运算符 Size of struct in C C中的struct大小 We know that a struct size is not only the summation of all the data members, rather its the minimum sum guaranteed. …

ELK系列~对fluentd参数的理解

这段时候一直在研究ELK框架,主要集成在对fluentd和nxlog的研究上,国内文章不多,主要看了一下官方的API,配合自己的理解,总结了一下,希望可以帮到刚入行的朋友们! Fluentd(日志收集与…

css 文本背景色透明_如何使用CSS将文本或图像的背景设置为透明?

css 文本背景色透明Introduction: 介绍: In web development, there are numerous ways by which we can style our websites or web pages. You can make use of lots of properties for creating attractive and responsive websites. 在Web开发中,我…

一次前端笔试总结

1.有一个长度未知的数组a,如果它的长度为0就把数字1添加到数组里面,否则按照先进先出的队列规则让第一个元素出队。 分析:这道题主要是考核了数组的队列方法和栈方法。另外,原题还有字数限制的,只有在字数小于30并且结…

SSL

今天遇到一位网友要求老蒋将他当前已经在使用的WDCP面板环境,给某个站点添加SSL证书,实现HTTPS网址访问。在过去的几篇文章中,老蒋也有分享过不少在Linux VPS中对应的WEB环境安装SSL证书的经历,其实总体来看都大同小异&#xff0c…

应用宝认领应用

2019独角兽企业重金招聘Python工程师标准>>> 【Android】命令行jarsigner签字和解决找不到证书链错误 1、签名失败 $jarsigner -verbose -keystore /Volumes/Study/resourcesLib/Qunero-achivements/AndroidApp/QuLordy-signed-key -signedjar ./signed_XiaomiVerif…

Squid服务日志分析

Squid服务日志分析 Apache 和 Squid 是两种著名的代理缓存软件,但Squid 较 Apache 而言是专门的代理缓存服务器软件,其代理缓存的功能强大,支持 HTTP/1.1 协议,其缓存对象也较多;并且 Squid 的缓存管理模块和访问控制模…

云时代 揭开性能监测战略的隐秘优势

云时代的性能监测战略 能够对各种变化做出快速响应而不偏离重心和企业发展动力,正逐渐成为各行各业、各种规模企业的奋斗目标。业务敏捷性通常是运营良好,可实现盈利的企业标志。实现这一目标意味着公司已经成功地利用业务关键型技术来提高生产率&#x…

聊聊全站HTTPS带来的技术挑战

日前写的文章里了讨论了数据传输的安全性的问题,最后一部分提到了通过HTTPS解决数据传输安全性的方案。那么一个新问题又来了,实施全站HTTPS的过程中,我们可能会遇到哪些技术问题?所以我今天和大家一起来算一下这个账,将技术成本…

4.3/4.4 磁盘分区

2019独角兽企业重金招聘Python工程师标准>>> 添加虚拟磁盘 第一步,选择虚拟机中的“设置” 第二步,选择“添加硬盘” 第三步,选择_SCSI (推荐) # 保持默认 第四步,选择“创建新的虚拟磁盘…

RoboMaster 2017:机器人版的「王者农药」,工程师们的竞技时代

8月6日晚,第十六届全国大学生机器人大赛 RoboMaster 2017机甲大师赛在华润深圳湾体育中心“春茧”体育馆举行,关于这个比赛的盛况已经无需赘述,去年雷锋网参加上届比赛时,报道的是「像看了一场演唱会」,如果用演唱会来…

【初学者必读】:前端工程师的知识体系

下图是前端工程师图解: 前端开发的核心是HTML CSS JavaScript。本质上它们构成一个MVC框架,即HTML作为信息模型(Model),CSS控制样式(View),JavaScript负责调度数据和实现某种展现逻…

使用Prometheus监控Cloudflare的全球网络

Matt Bostock在SRECON 2017欧洲大会的演讲中,介绍了如何使用Prometheus实现对CloudFlare分布于全球的架构和网络的监控。Prometheus是一种基于度量进行监控的工具,CloudFlare是一家CDN、DNS和DDoS防御(Mitigation)服务提供商。\\基…