[看书笔记]《深入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,一经查实,立即删除!

相关文章

[转载] 【零基础学爬虫】python中的yield详解

参考链接: 什么时候在Python中使用yield而不是return python中的yield功能比较强大,什么意思呢?如果一个函数f内使用了yield关键词,那么该函数就可以这样使用: for item in f(***): **** 也就是包含yield关键词的函…

全新的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语言100位整数变量声明_C ++程序动态声明一个整数变量并打印其内存地址

c语言100位整数变量声明Here, we will learn how we can declare an integer variable dynamically and how to print address of declared memory block? 在这里,我们将学习如何动态声明整数变量,以及如何打印声明的内存块的地址? In C pr…

[转载] python 函数返回多个值

参考链接: 在Python中返回多个值 (廖雪峰Python教程学习笔记) 函数体内部的语句在执行时,一旦执行到return,函数就执行完毕,并将结果返回。 如果没有return语句,函数执行完毕后也会返回结果…

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

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

[转载] Python中定义函数,循环语句,条件语句

参考链接: Python中的局部函数 由于日常程序流中主要是三种结构:顺序,循环,条件,且往往需要自定义函数再调用, 因此今天想学习一下Python中关于定义函数、循环语句和条件语句的写法。 1.定义函数 区…

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. 在上一篇文章中,我们介绍了护照本地身份验证策略的实现…

vue2.0 引用qrcode.js实现获取改变二维码的样式

vue代码 <template><div class"qart"><div id"qrcode" ref"qrcode"></div><input type"text" id"getval" value"" placeholder"修改这个值改变二维码"></div> <…

[转载] Python列表排序 list.sort方法和内置函数sorted

参考链接&#xff1a; Python中的函数 Python列表排序 list.sort方法和内置函数sorted 很多时候我们获取到一个列表后,这个列表并不满足我们的需求,我们需要的是一个有特殊顺序的列表. 这时候就可以使用list.sort方法和内置函数sorted,本文就是介绍list.sort方法和sorted内…

Java Thread类最终同步的void join(long time_in_ms)方法,带有示例

线程类最终同步无效连接(long time_in_ms) (Thread Class final synchronized void join(long time_in_ms)) This method is available in package java.lang.Thread.join(long time_in_ms). 软件包java.lang.Thread.join(long time_in_ms)中提供了此方法。 join(long time_in_…

RYU控制器安装`

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

[转载] mac开发者,你不得不知道的环境变更设置方法(如Java的环境变更 source命令 )

参考链接&#xff1a; 设置Java环境 Mac是基于Unix的&#xff0c;所有先来几个常识与命令&#xff1a; Unix中双引号单引号反引号(" )的区别 Unix中双引号起到“弱引用”的作用:被引用的字符大部分被按照字符字面的意思解释执行&#xff0c;除了了$,\,字符除外。 [因…

人形机器人正在美国史密森尼博物馆中担任导游的工作

Te article has been removed, please visit IncludeHelps home page for more articles 该文章已被删除&#xff0c;请访问IncludeHelp的主页以获取更多文章翻译自: https://www.includehelp.com/News/a-humanoid-robot-is-doing-the-job-of-a-guide-in-the-smithsonian-museu…

normalizr API

APInormalizedenormalizeschemaArrayEntityObjectUnionValuesnormalize(data, schema)Normalizes input data per the schema definition provided. 根据提供的schema定义规范化输入数据。data: required Input JSON (or plain JS object) data that needs normalization.schem…

[转载] 【Java】基础06:HelloWorld入门程序

参考链接&#xff1a; 从Hello World示例开始Java编程 HelloWorld它的中文意思是&#xff1a;“你好&#xff0c;世界”。 仿佛代表着计算机对世界说出来的第一句话&#xff0c;因为它简洁实用&#xff0c;所以被作为入门程序广泛使用。 Java程序开发三步骤&#xff1a;编…

[转载] Java中的命名参数

参考链接&#xff1a; Java命名约定 创建具有许多参数的方法是一个主要的缺点。 每当需要创建这样的方法时&#xff0c;就在空气中闻一闻&#xff1a;这是代码的味道。 强化单元测试&#xff0c;然后进行重构。 没有借口&#xff0c;没有屁股。 重构&#xff01; 使用构建器模…

[转载] JVM(一):JVM体系结构详解

参考链接&#xff1a; JVM如何工作–JVM体系结构 JVM简介 JVM是Java程序得以运行的平台&#xff0c;也是Java程序可以跨平台的底层支撑&#xff0c;从整体上来看&#xff0c;JVM的主要功能可以分为加载和执行两大块。其中类加载器负责.class文件的寻址与加载&#xff0…

数据库连接池的设计思路及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…

[转载] java虚拟机 jvm 出入java栈 栈空间内存分配

参考链接&#xff1a; Java虚拟机(JVM)堆栈区域 java栈空间是一块线程私有的内存空间&#xff0c;java堆和程序数据密切相关&#xff0c;那么java栈就是和线程执行密切相关。线程最基本的执行行为就是函数的调用。每次函数调用其实是通过java栈传递数据的。 数据结构中的栈的…

SVN命令行更新代码

命令列表 svn help查看帮助信息 Available subcommands: add auth blame (praise, annotate, ann) cat changeli…