深入Java虚拟机之虚拟机体系结构
工作以来,代码越写越多,程序也越来越臃肿,效率越来越低,对于我这样一个追求完美的程序员来说,这是绝对不被允许的,于是除了不断优化程序结构外,内存优化和性能调优就成了我惯用的“伎俩”。
要对Java程序进行内存优化和性能调优,不了解虚拟机的内部原理(或者叫规范更严谨一点)是肯定不行的,这里推荐一本好书《深入Java虚拟机(第二版)》(Bill Venners著,曹晓刚 蒋靖 译,实际上本文正是作者阅读本书之后,对Java虚拟机的个人理解阐述)。当然了,了解Java虚拟机的好处并不仅限于上述两点好处。从更深一点的技术层面上看,了解Java虚拟机的规范和实现,将更加有助于我们编写高效、稳定的Java代码。比如,假如了解Java虚拟机的内存模型,了解虚拟机的内存回收机制,那么我们就不会过分依赖它,而会在需要的时候显式的"释放内存"(Java代码不能显式释放内存,但是可以通过释放对象引用告知垃圾回收器回收该对象需要被回收),以降低不必要的内存消耗;假如我们了解Java栈的工作原理,那么我们就可以通过减少递归层数,减少循环次数来降低堆栈溢出的风险。可能对于应用开发人员来说,可能不会直接去涉及这些Java虚拟机底层实现的工作,但是了解这些背景知识,或多或少,都会对我们写的程序产生潜移默化的好的影响。
本篇文章,将简明扼要的说明Java虚拟机的体系结构和内存模型,如有用词不妥或解释不准确之处,请不吝指正,深感荣幸!
Java 虚拟机体系结构
类装载子系统
Java虚拟机有两种类装载器,分别是启动类装载器和用户自定义装载器。
通类装载子系统通过类的全限定名(包名和类名,网络装载还包括 URL)将 Class 装载进运行时数据区。对于每一个被装载的类型,Java虚拟机都会创建一个java.lang.Class类的实例来代表该类型,该实例被放在内存中的堆区,而装载的类型信息则位于方法区,这一点和所有其他对象都是一样的。
类装载子系统在装载一个类型前,除了要定位和导入对应的二进制class文件外,还要验证导入类的正确性,为类变量分配并初始化内存,以及解析符号引用为直接引用,这些动作严格按照以下顺序进行:
1)装载——查找并装载类型的二进制数据;
2)连接——执行验证,准备以及解析(可选)
3)验证 确保被导入类型的正确性
4)准备 为类变量分配内存,并将其初始化为默认值
5)解析 把类型中的符号引用转换为直接应用
方法区
对于每一个被类装载子系统装载的类型,虚拟机都会保存下列数据到方法区:
◆ 类型的全限定名
◆ 类型超类的全限定名(java.lang.Object没有超类)
◆ 类型是类类型还是接口类型
◆ 类型的访问修饰符
◆ 任何直接超接口的全限定名有序列表
除了上述基本类型信息,还将保存如下信息:
◆ 类型的常量池
◆ 字段信息(包括字段名、字段类型、字段修饰符)
◆ 方法信息(包括方法名、返回类型、参数的数量和类型、方法修饰符,如果方法不是抽象和本地的,还将保存方法的字节码、操作数栈和该方法栈帧中的局部变量区的大小和异常表)
◆ 常量以外的所有类变量(其实就是类的静态变量,因为静态变量是所有实例共享的,且与类型直接相关,所以他们是类一级的变量,作为类的成员被保存在方法区)
一个到类ClassLoader的引用
//返回的就是刚才保存的ClassLoader引用 String.class.getClassLoader(); |
一个到Class类的引用
//将返回刚才保存的Class类的引用 String.class; |
注意,方法区也是可以被垃圾回收器回收的。
堆
Java程序在运行时创建的所有类实例或数组都放在同一个堆中,而每一个Java虚拟机也是有一个对空间,所有线程共享一个堆(这就是一个多线程的Java程序会产生对象访问的同步问题的原因了)。
由于每一种Java虚拟机都有对虚拟机规范的不同实现,所以我们可能不知道每一种Java虚拟机在堆中是以何种形式表示对象实例的,不过我们可以通过下面这可能的实现来一窥端倪:
程序计数器
对于运行中的Java程序而言,每一个线程都有自己的PC(程序计数器)寄存器,它是在该线程启动时创建的,大小为一个字长,用来保存需要被执行的下一行代码的位置。
Java栈
每一个线程都有一个Java栈,以栈帧为单位保存线程的运行状态。虚拟机对Java栈的操作有两种:压栈和出栈,二者都已帧为单位。栈帧保存了传入参数、局部变量、中间运算结果等数据,在方法完成时被弹出,然后释放。
看一下两个局部变量相加时栈帧的内存快照
本地方法栈
这是 Java 调用操作系统本地库的地方,用来实现 JNI(Java Native Interface,Java 本地接口)
执行引擎
Java虚拟机的核心,控制装入 Java 字节码并解析;对于运行中的Java程序而言,每一个线程都是一个独立的虚拟机执行引擎的实例,从线程生命周期的开始到结束,他要么在执行字节码,要么在执行本地方法。
本地接口
连接了本地方法栈和操作系统库。
注:文中所有提到“Java虚拟机”的地方都是指“JavaEE和JavaSE平台的Java虚拟机规范”。
本文出自seven的测试人生公众号最新内容请见作者的GitHub页:http://qaseven.github.io/
相关文章:
【通俗理解线性代数】 -- 内积与相关
本图文从向量内积的角度引出了概率论中的相关系数,说明向量内积是线性相似性的表征。

java modelmapper_java - 使用ModelMapper映射抽象类型的字段 - SO中文参考 - www.soinside.com...
我有以下课堂知识层次:public abstract class Base {protected Boolean baseBoolean;}public class A extends Base {private BigDecimal amount;}并且尝试将DTO映射到实体public class DTO {private Base details;}public class Entity {private Base details;}并映…

基于Dialog的MFC程序在启动时隐藏为托盘程序(四)
这部分说一下如何加menu。。如果做小气球。。mfc的menu确是不如C#活着java那么easy..首先在rc里添加menu资源。。然后在ui界面里先设置一下你的菜单。。在第(二)部分已经简单知道了怎么取得tray的鼠标左右点击事件。。下面我们就把左右点击事件分开。。C…
【通俗理解线性代数】 -- 理解二次型
本微信图文介绍了二次型的几何意义以及正定在函数极值中的应用。

《Clojure数据分析秘笈》——1.6节从JDBC数据库读取数据
本节书摘来自华章社区《Clojure数据分析秘笈》一书中的第1章,第1.6节从JDBC数据库读取数据,作者(美)Eric Rochester,更多章节内容可以访问云栖社区“华章社区”公众号查看 1.6 从JDBC数据库读取数据从关系型数据库中读…

java timer cron_Java之旅--定时任务(Timer、Quartz、Spring、LinuxCron)
在Java中,实现定时任务有多种方式。本文介绍4种。Timer和TimerTask、Spring、QuartZ、Linux Cron。以上4种实现定时任务的方式。Timer是最简单的。不须要不论什么框架,只JDK就能够。缺点是不过个时间间隔的定时器,调度简单。Spring和QuartZ都…

诗歌rails之如何写一个简单的Rails Plugin
生成plugin骨架代码: Ruby代码 ruby script\generate plugin MyPlugin ruby script\generate plugin MyPlugin 功能需求: 在BlogController中把所有符合条件的Post(Model)生成为xml 如果不使用插件,很easy : in BlogController Ruby代码 def export_to_xml posts Post.fin…
【通俗理解线性代数】 -- 施密特正交化与QR分解
我们介绍线性代数知识的时候,稍微扩展一点,就能演变成一个新的角度。

iOS实现tableViewCell或collectionCell中点击界面按钮跳转
//找到父类界面 - (UIViewController *)viewController { for (UIView* next [self superview]; next; next next.superview) { UIResponder *nextResponder [next nextResponder]; if ([nextResponder isKindOfClass:[UIViewController class]]) { return (UIViewControlle…

java web 怎么用solr_使用web过滤器增加solr后台登录验证
solr后台自带是没有登录功能的,默认访问地址是:http://localhost:8983/solr/#/(内置jetty运行)。要给sorl后台增加登录验证方法:1、使用web服务器的登录验证(例如jetty、tomcat)这种方式好处是不需要另外写代码,只需配置一下对应的…

《程序设计解题策略》——1.6 利用左偏树实现优先队列的合并
本节书摘来自华章计算机《程序设计解题策略》一书中的第1章,第1.6节,作者:吴永辉 王建德 更多章节内容可以访问云栖社区“华章计算机”公众号查看。 1.6 利用左偏树实现优先队列的合并 优先队列在程序设计竞赛中十分常见,在统计问题、最值问…

Jquery JQZoom Plugin 放大鏡效果 Two
Jquery JQZoom Plugin 放大鏡效果 TwoJquery1.3.2Lib下載地址:http://files.cnblogs.com/davidzhou/jquery-1.3.2.rar插件下載地址:http://files.cnblogs.com/davidzhou/jqzoom_v2.2.rarDemo下載地址:http://files.cnblogs.com/davidzhou/MagnifySol.rar…

如何建立和维护自己的“人脉”
小故事1: 她打开房门,发现自家的门口竟然多了一条死鱼,她感到十分晦气,于是马上扔到垃圾桶了,过了一会儿,又有一条死鱼躺在自家门口,她还是扔了。为了抓住那个做恶作剧的人,她选择待…

java字符串统计英文字符用什么不同_JAVA程序。输入一行字符,分别统计出其中英文字母、空格、数字和其它字符的个数。...
展开全部一、问题分析:输入32313133353236313431303231363533e58685e5aeb931333363373764一行字母,那么会以换行结束。所以可以存入数组,也可以逐个输入,遇到换行结束。要统计各个类的个数,就要逐个判断是哪个分类的。…

COMVariantType的Date类型
刚跟一个同事讨论通过CCADOConnection读取外部数据库数据的问题,如果读取的数据是DateTime类型,只能得到Date部分,Time部分被忽略了。查看类CCADOField的value方法找到问题所在,下面是MSDN上关于COMVariant的Date方法的Remark&…

《树莓派Python编程指南》——2.2 一个Python游戏:猫和老鼠
本节书摘来自华章计算机《树莓派Python编程指南》一书中的第2章,第2.2节,作者:(美) Alex Bradbury Ben Everard更多章节内容可以访问云栖社区“华章计算机”公众号查看。 2.2 一个Python游戏:猫和老鼠 现在ÿ…
【通俗理解线性代数】 -- 理解行列式
本微信图文主要从几何与变换的角度介绍了行列式的意义。

solr java score_Solr 按照得分score跟指定字段相乘排序
CentOS6.5 mysql 5.5安装CentOS 6 mysql5.5安装配置 1 安装所需软件 2 安装cmake 3 tar.gz形式安装mysql 4 配置与启动 MySQL自5.5版本以后,就开始使用cmake编译工具了.tar ...access数据库select查询top时无效的解决办法access数据库select查询top时有时…

Mantis 缺陷管理系统配置与安装
搭建Mantis 缺陷管理系统 By Snooper 错误必有!欢迎指正! 什么是Mantis MantisBT is a free popular web-based bugtracking system (feature list). It is written in the PHP scripting language and works with MySQL, MS SQL, and PostgreSQL datab…
【Matlab数据的可视化】自适应绘图函数fplot
今天看到fplot这个函数,于是乎赶快整理出来放到“Matlab数据的可视化”这个板块中,以便更好的完善我们的知识结构。

大数据时代涉军网络舆情引导的“5个结合”
随着信息技术发展,大数据构成了一种新的传播技术环境,重塑了网络舆情生态,给社会舆情体系带来了重大而深刻的变化,使网络舆情在整个社会舆情体系中地位更加凸显、作用更加突出。必须从维护国家政治安全的高度,深入探索…

java http head 请求_http请求头header、请求体body、请求行介绍
HttpServletRequest对象代表客户端的请求,当客户端通过http协议请求访问服务器的时候,http请求头的所有信息都封装在这个对象中,通过这个对象,可以获取客户端请求的所有信息。http请求包含请求行/状态行、请求头、请求体。request如果是post才有请求体&a…

全球UML模型共享设计下载中心--www.euml.org上线
全球UML模型共享设计&下载中心euml.org上线euml.org是楚凡科技版权所有的公益站点,为全球UML用户和爱好者提供如下服务:1、在线UML建模工具Trufun eUML。Trufun eUML以Applet形式运行在客户的浏览器中,从而提供在线建模功能。2、模型共享…

你是否对它有一种责任感
它,指开发人员对开发出的产品;它是测试人员所面对的测试产品。你是否对它有一种责任感,是指开发人员是否对它开发出来的产品有责任感,为它骄傲,为它而开心;你是否对它有一种责任感,是指测试人员…
【机器学习】基于粒子群算法的非线性函数寻优
本微信图文介绍了基于粒子群算法的非线性函数寻优过程,并利用Matlab实现。

java递归排雷_C语言实现扫雷小游戏
源代码链接:https://github.com/Sasura321/Minesweeper扫雷游戏也算是一个简单的小项目,这儿是之前写的代码,来写成博文回顾一下。首先,代码要实现几个功能:第一下扫雷时,即使踩中了雷也不能直接炸死;扫雷时࿰…

任意角度旋转图片
/// <summary> /// 任意角度旋转 /// </summary> /// <param name"bmp">原始图Bitmap</param> /// <param name"angle">旋转角度</param> /// <param name"bkColor"…

如何切分用户故事
在把用户故事切分成小块,从而更好地利用敏捷技术时,很多新组建的敏捷团队都会遇到困难。 敏捷社区的成员在多篇文章中为如何有效地切分用户故事提供了指导。 当把庞大的用户故事切分成小块时,是否有一些一般的准则供我们遵循呢? Rachel D…
【机器学习】基于人工鱼群算法的非线性函数寻优
本微信图文介绍了人工鱼群算法的基本原理并对一元非线性函数进行极值寻优。

java9可执行jar_单个java文件打成可执行jar包
1 概述使用JDK自带的jar与java将单个java文件打成可执行jar包并运行。 当然也可以使用IDE完成,使用Maven只需要一个简单的package,但是单个文件嘛,没必要这么“凶狠”。2 新建测试文件著名的Hello World:public class Main{public…