《分布式Java应用之基础与实践》读书笔记四
Java代码作为一门跨操作系统的语言,最终是运行在JVM中的,所以对于JVM的理解就变得非常重要了。整体上,我们可以从三个方面来深入理解JVM。
- Java代码的执行
- 内存管理
- 线程资源同步和交互机制
Java程序运行在JVM上,JVM的运行状况对于Java程序而言会产生很大的影响,因此,掌握JVM中的关键机制对于编写稳定、高性能的Java程序很重要。首先,我们看看JVM规范定义的标准结构图:

JVM负责转载class文件并执行,因此,首先要掌握的是JDK如何将Java代码编译为class文件、如何转载class文件及如何执行class。将源码编译为class文件的实现取决于各个JVM实现或各种源码编译器;class文件通常有类加载器来完成加载;class的执行在Sun JDK中有解释执行和编译为机器码执行两种方式,其中编译为机器码又分为client和server两种模式。Sun JDK为了提升class的执行效率,对于解释执行和编译为机器码执行都设置了很多的优化策略。Java程序无需显示的分配和回收内存,因此JVM如何进行内存的分配和回收也是要关注的问题。JVM提供了多线程的支持,对于分布式Java应用而言,通常要借助线程来实现高并发,因此JVM中线程资源同步的机制及线程之间交互的机制也是需要掌握的。
Java代码的执行机制
Java源码编译机制
JVM规范定义了class文件的格式,但并没有定义Java源码如何编译成class文件,各厂商自行实现编译器,例如Sun JDK中的javac。

下面简单介绍以上三个步骤:
- 分析和输入到符号表(Parse and Enter):Parse过程主要是词法分析和语法分析,将代码字符串 ---> token序列 ---> 抽象语法树;Enter过程主要将符号输入到符号表,包括确定类的超类型和接口、添加默认构造器,符号输入符号表等
- 注解处理(Annotation Processing):主要处理用户自定义的annotation,可基于annotation来生成附加代码或进行一些特殊的检查。
- 语义分析和生成class文件(Analyse and Generate):Analyse过程主要基于抽象语法树进行一系列的语义分析。包括将语法树中的名字、表达式等元素与变量、方法、类型等联系到一起;检查变量使用前是否已声明;推导泛型方法的类型参数;...;将含有语法糖的语法树改为含有简单语法结构的语法树等。Generate过程主要是将实例成员初始化器收集到构造器中,将静态成员初始化器收集为();将抽象语法树生成字节码,采用后序遍历语法树,并进行最后少量代码转换(String相加转变为StringBuilder操作);最后从符号表生产class文件。
class文件中并不仅仅存放了字节码,还存放了很多辅助jvm来执行class的附加信息,一个class文件包括了一下信息:
- 结构信息:格式版本号及各部分的数量与大小的信息
- 元数据:可简单对应Java源码中"声明"与"常量"的信息
- 方法信息:可简单对应Java源码中"语句"与"表达式"的信息
假设有如下一段简单的代码:
public class Foo {
private static final int MAX_COUNT=1000;
private static int count=0;
public int bar() throws Exception {
if(++count >= MAX_COUNT) {
count = 0;
throw new Exception("count overflow");
}
return count;
}
}
// 执行javac -g Foo.java 编译此源码,之后通过 javap -c -s -l -verbose Foo 来参看编译后的class文件
// 类继承的超类/实现的接口的声明信息
public class Foo extends java.lang.Object
SourceFile: "Foo.java"
// class文件格式版本号
minor version: 0
major version: 50
// 常量池,存放所有Field名称、方法名、方法签名、类型名、代码及class文件中的常量值
Constant pool:
const #1 = Method #7.#27; // java/lang/Object."<init>":()V
const #2 = Field #6.#28; // Foo.count:I
const #3 = class #29; // java/lang/Exception
const #4 = String #30; // count overflow
const #5 = Method #3.#31; // java/lang/Exception."<init>":(Ljava/lang/String;)V
...
const #34 = Asciz (Ljava/lang/String;)V;
{
// 将符号输入到符号表时生成的默认构造器方法
public Foo();
...
// bar方法的元数据信息
public int bar() throws java.lang.Exception;
Signature: ()I
// 对应字节码的源码行号信息
LineNumberTable:
line 9: 0
line 10: 15
line 11: 19
// 局部变量信息,和方法绑定,接口没有方法体,所以ASM之类的在获取接口方法时,是拿不到方法中参数的信息
LocalVariable:
Start Length Slot Name Signature
0 33 0 this LFoo;
Code:
Stack=3, Locals=1, Args_size=1
// 方法对应的字节码
0:getstatic #2; // Field count:
...
// 记录有分支的情况
StackMapTable: number_of_entries=1
frame_type=29 /* same */
// 异常处理器表
Exceptions:
throws java.lang.Exception
...
}
从以上可见,class文件是个完整的自描述文件,字节码在其中只占了很小的部分,源码编译为class文件后,即可放入jvm中执行。执行时jvm首先要做的是装载class文件,这个机制称为类加载机制。
《分布式Java应用之基础与实践》读书笔记四的更多相关文章
- 【鸟哥的Linux私房菜】笔记1
Linux是什么 从操作系统与cpu架构关系到linux Richard Mathew Stallman GPL 关于GNU计划 Linux的发展 Linux的核心版本 Linux的特色 Linux ...
- 【鸟哥的Linux私房菜】笔记3
正确地开机 最好不要使用root账号登陆!GNOME图形界面 View items as a list X WindowShell 文本交互界面bash是Shell的名称,Linux的默认壳程序就是b ...
- 【鸟哥的Linux私房菜】笔记2
Linux的应用 学习资源整理 安装记录 >< 1.Linux的应用: 网络服务器 数据库 学术机构的高效运算任务 嵌入式系统 ... 2.挂载与磁盘分区 学习资源整理 学习 1.书上的网 ...
- 《鸟哥的Linux私房菜》笔记——02. 关于Linux
Unix 历史 1969年以前:伟大的梦想--Bell, MIT 与 GE 的「Multics」系统 1969年:Ken Thompson 的小型 file server system 1973年:U ...
- 《鸟哥的Linux私房菜》笔记——03. 磁盘分区
Everything is a file. 常见硬件对应于 Linux 下的文件(/dev目录下) 装置 装置在Linux内的档名 SCSI/SATA/U盘硬盘机 /dev/sd[a-p] U盘 /d ...
- 鸟哥的linux私房菜学习笔记 __ 命令与文件的搜寻
连续输入两次[tab]按键就能够知道使用者有多少命令可以下达.那你知不知道这些命令的完整档名放在哪里?举例来说,ls 这个常用的命令放在哪里呢? 就透过 which 或 type 来找寻吧! 范例一: ...
- 【鸟哥的Linux私房菜】笔记
操作系统核心的功能! 驱动程序与操作系统的关系 2. [计算机组成之组件] 3.CPU实际要处理的数据完全来自于主存储器,这是一个很重要的概念! 4.CPU是整个计算机系统最重要的部分,那么目前世界上 ...
- 《鸟哥的Linux私房菜》笔记——04. 简单命令行
键入命令 [dmtsai@study ~]$ command [-options] parameter1 parameter2 ... 指令 選項 參數(1) 參數(2) 注意:有时也可以使用 + 放 ...
- 鸟哥的Linux私房菜学习笔记——文件权限与目录配置
Linux的文件权限和目录配置 在linux中的每个用户必需属于一个组,不能独立于组外.在linux中每个文件有所有者.所在组.其它组的概念. (1)所有者 一般为文件的创建者,谁创建了该文件,就是天 ...
- 鸟哥的Linux私房菜学习笔记(1)
2014/10/29 1.档案的权限管理分为三个部分: 拥有者.群组.其他 2.ls -al 命令可以看到档案的详细信息 3.档案的属性中由十个部分构成 第一个部分是档案类型 -代表档案.d代表文件夹 ...
随机推荐
- 你可记得曾经的-------- C#面向对象的“基础”
1.C#中构造函数定义的理解: ①构造函数名与所在的类名相同 ②构造函数可以重载 ③构造函数可以带参数 ④构造函数没有返回值,且不允许写出void,可以有参也可以无参 ...
- C各个类型的大小
1个字节(byte)是8bit. 我采用的是64位系统,64位指CPU寄存器的数据宽度是64位的. short 和 int:short比int更节省空间,short占内存是Int的一半,当要考虑程序的 ...
- 一名合格的JAVA程序员需要点亮那些技能树?
这是从450家企业的招聘信息中统计而来,相对来说还是比较真实的,虽然有些公司的招聘要求万年不变,但还是可以大致反应企业的招聘要求的. 尽管Struts2漏洞频出,但是由于政府.银行以及传统企业遗留项目 ...
- 【转】并行类加载——让tomcat玩转双十一 @双十一实战
原文:https://yq.aliyun.com/articles/4227?spm=5176.100239.yqblog1.20.cfRztB 摘要: 今年双十一,是应用容器的最新版本Ali-tom ...
- 《C++之那些年踩过的坑(三)》
C++之那些年踩过的坑(三) 作者:刘俊延(Alinshans) 本系列文章针对我在写C++代码的过程中,尤其是做自己的项目时,踩过的各种坑.以此作为给自己的警惕. [版权声明]转载请注明原文来自:h ...
- Vue.js 插件开发详解
前言 随着 Vue.js 越来越火,Vue.js 的相关插件也在不断的被贡献出来,数不胜数.比如官方推荐的 vue-router.vuex 等,都是非常优秀的插件.但是我们更多的人还只停留在使用的阶段 ...
- sql server 去除字符中空格的方法
用的是REPLACE ( original-string, search-string, replace-string )方法,这三个参数分别是:原字符串.要替换的字符串.替换成的字符串 比如:UPD ...
- 踩坑实录 使用 cardview 时报错 error: No resource identifier found for attribute 'cardCornerRadius' in package 'com.xxxxx.xxx'
在项目中引用 cardview 卡片布局,编译时 Android Studio 报出下面图片中红框标记的错误: 出现这种情况的原因在于没有导入 cardview 卡片布局相应的依赖包,因此我们需要在 ...
- 使用 SLF4J + LogBack 构建日志系统(转)
转载自:http://www.cnblogs.com/mailingfeng/p/3499436.html 上次我们讨论了如何选择一个好的开源日志系统方案,其中的结论是:使用 SLF4J + LogB ...
- es suggest did you mean资料
term suggester 功能介绍 term suggester 根据提供的文档提供搜索关键词的建议,也就是关键词自动纠错.该链接介绍如何使用 term suggester 语法.term sug ...