- 浏览: 332241 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (140)
- oracle (2)
- j2se (18)
- 应用服务器 (2)
- 操作系统 (21)
- j2ee (3)
- web (9)
- Junit (0)
- 项目 (0)
- IDE (0)
- 五花八门 (1)
- excel导入导出 (0)
- DWR (0)
- display标签总结 (0)
- JS (7)
- FCKeditor (0)
- Spring (3)
- webservice (1)
- JVM (14)
- 传输协议 (6)
- maven (3)
- 服务器 (2)
- 数据结构 (11)
- HTTPClient (2)
- JQUERY (9)
- 设计模式 (4)
- 数据库 (6)
- 看书笔记 (0)
- 工具 (4)
- MINA (3)
- mysql (5)
- jetty (1)
- JAVA网络编程 (7)
- Hessian (1)
- ibatis (1)
- socket (4)
- Native (1)
- http (2)
- nosql (2)
- linux (1)
- hadoop (1)
最新评论
-
applezjv:
可以...
maven常见问题 -
andyboy_bin:
p
Jetty -
ye_wx:
...
TableSpace -
ye_wx:
TableSpace -
极限_裁决:
引用第二:不要把“好像”;“有人会……”;“大概”;“晚些时候 ...
可以让你少奋斗10年的工作经验
原文:http://www.iteye.com/topic/821872
1 JVM 简介
JVM 是我们Javaer 的最基本功底了,刚开始学Java 的时候,一般都是从“Hello World ”开始的,然后会写个复杂点class ,然后再找一些开源框架,比如Spring ,Hibernate 等等,再然后就开发企业级的应用,比如网站、企业内部应用、实时交易系统等等,直到某一天突然发现做的系统咋就这么慢呢,而且时不时还来个内存溢出什么的,今天是交易系统报了StackOverflowError ,明天是网站系统报了个OutOfMemoryError ,这种错误又很难重现,只有分析Javacore 和dump 文件,运气好点还能分析出个结果,运行遭的点,就直接去庙里烧香吧!每天接客户的电话都是战战兢兢的,生怕再出什么幺蛾子了。我想Java 做的久一点的都有这样的经历,那这些问题的最终根结是在哪呢?—— JVM 。
JVM 全称是Java Virtual Machine ,Java 虚拟机,也就是在计算机上再虚拟一个计算机,这和我们使用 VMWare 不一样,那个虚拟的东西你是可以看到的,这个JVM 你是看不到的,它存在内存中。我们知道计算机的基本构成是:运算器、控制器、存储器、输入和输出设备,那这个JVM 也是有这成套的元素,运算器是当然是交给硬件CPU 还处理了,只是为了适应“一次编译,随处运行”的情况,需要做一个翻译动作,于是就用了JVM 自己的命令集,这与汇编的命令集有点类似,每一种汇编命令集针对一个系列的CPU ,比如8086 系列的汇编也是可以用在8088 上的,但是就不能跑在8051 上,而JVM 的命令集则是可以到处运行的,因为JVM 做了翻译,根据不同的CPU ,翻译成不同的机器语言。
JVM 中我们最需要深入理解的就是它的存储部分,存储?硬盘?NO ,NO , JVM 是一个内存中的虚拟机,那它的存储就是内存了,我们写的所有类、常量、变量、方法都在内存中,这决定着我们程序运行的是否健壮、是否高效,接下来的部分就是重点介绍之。
2 JVM 的组成部分
我们先把JVM 这个虚拟机画出来,如下图所示:
从这个图中可以看到,JVM 是运行在操作系统之上的,它与硬件没有直接的交互。我们再来看下JVM 有哪些组成部分,如下图所示:
该图参考了网上广为流传的JVM
构成图,大家看这个图,整个JVM
分为四部分:
q Class Loader 类加载器
类加载器的作用是加载类文件到内存,比如编写一个HelloWord.java 程序,然后通过javac 编译成class 文件,那怎么才能加载到内存中被执行呢?Class Loader 承担的就是这个责任,那不可能随便建立一个.class 文件就能被加载的,Class Loader 加载的class 文件是有格式要求,在《JVM Specification 》中式这样定义Class 文件的结构:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
需要详细了解的话,可以仔细阅读《JVM Specification 》的第四章“The class File Format ”,这里不再详细说明。
友情提示:Class Loader 只管加载,只要符合文件结构就加载,至于说能不能运行,则不是它负责的,那是由Execution Engine 负责的。
q Execution Engine 执行引擎
执行引擎也叫做解释器(Interpreter) ,负责解释命令,提交操作系统执行。
q Native Interface 本地接口
本地接口的作用是融合不同的编程语言为Java 所用,它的初衷是融合C/C++ 程序,Java 诞生的时候是C/C++ 横行的时候,要想立足,必须有一个聪明的、睿智的调用C/C++ 程序,于是就在内存中专门开辟了一块区域处理标记为native 的代码,它的具体做法是Native Method Stack 中登记native 方法,在Execution Engine 执行时加载native libraies 。目前该方法使用的是越来越少了,除非是与硬件有关的应用,比如通过Java 程序驱动打印机,或者Java 系统管理生产设备,在企业级应用中已经比较少见,因为现在的异构领域间的通信很发达,比如可以使用Socket 通信,也可以使用Web Service 等等,不多做介绍。
q Runtime data area 运行数据区
运行数据区是整个JVM 的重点。我们所有写的程序都被加载到这里,之后才开始运行,Java 生态系统如此的繁荣,得益于该区域的优良自治,下一章节详细介绍之。
整个JVM 框架由加载器加载文件,然后执行器在内存中处理数据,需要与异构系统交互是可以通过本地接口进行,瞧,一个完整的系统诞生了!
2 JVM 的内存管理
所有的数据和程序都是在运行数据区存放,它包括以下几部分:
q Stack 栈
栈也叫栈内存,是Java 程序的运行区,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束,该栈就Over 。问题出来了:栈中存的是那些数据呢?又什么是格式呢?
栈中的数据都是以栈帧( Stack Frame )的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法 (Method) 和运行期数据的数据集,当一个方法 A 被调用时就产生了一个栈帧 F1 ,并被压入到栈中, A 方法又调用了 B 方法,于是产生栈帧 F2 也被压入栈,执行完毕后,先弹出 F2 栈帧,再弹出 F1 栈帧,遵循“先进后出”原则。
那栈帧中到底存在着什么数据呢?栈帧中主要保存3 类数据:本地变量(Local Variables ),包括输入参数和输出参数以及方法内的变量;栈操作(Operand Stack ),记录出栈、入栈的操作;栈帧数据(Frame Data ),包括类文件、方法等等。光说比较枯燥,我们画个图来理解一下Java 栈,如下图所示:
图示在一个栈中有两个栈帧,栈帧2
是最先被调用的方法,先入栈,然后方法2
又调用了方法1
,栈帧1
处于栈顶的位置,栈帧2
处于栈底,执行完毕后,依次弹出栈帧1
和栈帧2
,线程结束,栈释放。
q Heap 堆内存
一个JVM 实例只存在一个堆类存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,以方便执行器执行,堆内存分为三部分:
Permanent Space 永久存储区
永久存储区是一个常驻内存区域,用于存放JDK 自身所携带的Class,Interface 的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭JVM 才会释放此区域所占用的内存。
Young Generation Space 新生区
新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分: 伊甸区(Eden space )和幸存者区(Survivor pace ),所有的类都是在伊甸区被new 出来的。幸存区有两个: 0 区(Survivor 0 space )和1 区(Survivor 1 space )。当伊甸园的空间用完时,程序又需要创建对象,JVM 的垃圾回收器将对伊甸园区进行垃圾回收,将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存0 区。若幸存0 区也满了,再对该区进行垃圾回收,然后移动到1 区。那如果1 区也满了呢?再移动到养老区。
Tenure generation space 养老区
养老区用于保存从新生区筛选出来的JAVA 对象,一般池对象都在这个区域活跃。 三个区的示意图如下:
q
Method Area
方法区
方法区是被所有线程共享,该区域保存所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。
q PC Register 程序计数器
每个线程都有一个程序计数器,就是一个指针,指向方法区中的方法字节码,由执行引擎读取下一条指令。
q Native Method Stack 本地方法栈
3 JVM 相关问题
问:堆和栈有什么区别
答:堆是存放对象的,但是对象内的临时变量是存在栈内存中,如例子中的 methodVar 是在运行期存放到栈中的。
栈是跟随线程的,有线程就有栈,堆是跟随 JVM 的,有 JVM 就有堆内存。
问:堆内存中到底存在着什么东西?
答:对象,包括对象变量以及对象方法。
问:类变量和实例变量有什么区别?
答:静态变量是类变量,非静态变量是实例变量,直白的说,有 static 修饰的变量是静态变量,没有 static 修饰的变量是实例变量。静态变量存在方法区中,实例变量存在堆内存中。
问:我听说类变量是在 JVM 启动时就初始化好的,和你这说的不同呀!
答:那你是道听途说,信我的,没错。
问: Java 的方法(函数)到底是传值还是传址?
答:都不是,是以传值的方式传递地址,具体的说原生数据类型传递的值,引用类型传递的地址。对于原始数据类型, JVM 的处理方法是从 Method Area 或 Heap 中拷贝到 Stack ,然后运行 frame 中的方法,运行完毕后再把变量指拷贝回去。
问:为什么会产生 OutOfMemory 产生?
答:一句话: Heap 内存中没有足够的可用内存了。这句话要好好理解,不是说 Heap 没有内存了,是说新申请内存的对象大于 Heap 空闲内存,比如现在 Heap 还空闲 1M ,但是新申请的内存需要 1.1M ,于是就会报 OutOfMemory 了,可能以后的对象申请的内存都只要 0.9M ,于是就只出现一次 OutOfMemory , GC 也正常了,看起来像偶发事件,就是这么回事。 但如果此时 GC 没有回收就会产生挂起情况,系统不响应了。
问:我产生的对象不多呀,为什么还会产生 OutOfMemory ?
答:你继承层次忒多了, Heap 中 产生的对象是先产生 父类,然后才产生子类,明白不?
问: OutOfMemory 错误分几种?
答:分两种,分别是“ OutOfMemoryError:java heap size ” 和” OutOfMemoryError: PermGen space ” ,两种都是内存溢出, heap size 是说申请不到新的内存了,这个很常见,检查应用或调整堆内存大小。
“ PermGen space ” 是因为永久存储区满了,这个也很常见,一般在热发布的环境中出现,是因为每次发布应用系统都不重启,久而久之永久存储区中的死对象太多导致新对象无法申请内存,一般重新启动一下即可。
问:为什么会产生 StackOverflowError ?
答:因为一个线程把 Stack 内存全部耗尽了,一般是递归函数造成的。
问:一个机器上可以看多个 JVM 吗? JVM 之间可以互访吗?
答:可以多个 JVM ,只要机器承受得了。 JVM 之间是不可以互访,你不能在 A-JVM 中访问 B-JVM 的 Heap 内存,这是不可能的。在以前老版本的 JVM 中,会出现 A-JVM Crack 后影响到 B-JVM ,现在版本非常少见。
问:为什么 Java 要采用垃圾回收机制,而不采用 C/C++ 的显式内存管理?
答:为了简单,内存管理不是每个程序员都能折腾好的。
问:为什么你没有详细介绍垃圾回收机制?
答:垃圾回收机制每个 JVM 都不同, JVM Specification 只是定义了要自动释放内存,也就是说它只定义了垃圾回收的抽象方法,具体怎么实现各个厂商都不同,算法各异,这东西实在没必要深入。
问: JVM 中到底哪些区域是共享的?哪些是私有的?
答: Heap 和 Method Area 是共享的,其他都是私有的,
问:什么是 JIT ,你怎么没说?
答: JIT 是指 Just In Time ,有的文档把 JIT 作为 JVM 的一个部件来介绍,有的是作为执行引擎的一部分来介绍,这都能理解。 Java 刚诞生的时候是一个解释性语言,别嘘,即使编译成了字节码( byte code )也是针对 JVM 的,它需要再次翻译成原生代码 (native code) 才能被机器执行,于是效率的担忧就提出来了。 Sun 为了解决该问题提出了一套新的机制,好,你想编译成原生代码,没问题,我在 JVM 上提供一个工具,把字节码编译成原生码,下次你来访问的时候直接访问原生码就成了,于是 JIT 就诞生了,就这么回事。
问: JVM 还有哪些部分是你没有提到的?
答: JVM 是一个异常复杂的东西,写一本砖头书都不为过,还有几个要说明的:
常量池( constant pool ):按照顺序存放程序中的常量,并且进行索引编号的区域。比如 int i =100 ,这个 100 就放在常量池中。
安全管理器( Security Manager ):提供 Java 运行期的安全控制,防止恶意攻击,比如指定读取文件,写入文件权限,网络访问,创建进程等等, Class Loader 在 Security Manager 认证通过后才能加载 class 文件的。
方法索引表( Methods table ),记录的是每个 method 的地址信息, Stack 和 Heap 中的地址指针其实是指向 Methods table 地址。
问:为什么不建议在程序中显式的生命 System.gc() ?
答:因为显式声明是做堆内存全扫描,也就是 Full GC ,是需要停止所有的活动的( Stop The World Collection ),你的应用能承受这个吗?
问: JVM 有哪些调整参数?
答:非常多,自己去找,堆内存、栈内存的大小都可以定义,甚至是堆内存的三个部分、新生代的各个比例都能调整。
发表评论
-
linux之uptime
2013-04-02 11:20 1809linux uptime命令主要用于获取主机运行时间和查询l ... -
服务器监控
2013-04-02 11:18 1294下面是我常用的几个主 ... -
java诊断工具
2013-04-01 19:12 1415jstack -- 如果java程序崩溃生成core文件,j ... -
linux 文件句柄打开过多的问题
2013-04-01 17:30 1577linux环境变量(转) Linux 的变 ... -
java枚举Enum
2013-01-14 14:43 1221public class TestEnum { /* ... -
Java 动态代理机制分析及扩展,第 1 部分
2012-03-26 12:47 777引言 Java 动态代理机制的出现,使得 Java 开 ... -
详解reflect Java的反射机制
2012-03-23 13:09 1019一、类型识别的两种方式: 首先了解一下“运 ... -
linux系统下修改权限
2012-02-14 19:21 1160Linux文件权限详解 ... -
umask命令
2012-02-14 19:14 1200linux常用指令 umask命令的一般格式: ... -
vi相关操作2
2012-02-14 18:14 872文本编辑器是所有计算机系统中最常用的一种工具。UNIX下的编辑 ... -
Linux下tar命令详解
2012-01-18 00:57 0Linux下tar命令详解 tar [-cxtz ... -
B树、B-树、B+树、B*树详解
2012-01-18 00:47 1969B树、B-树、B+树、B*树都是什么 B树 ... -
数据结构 二叉树(B树)
2012-01-18 00:41 1418BTree 特征: 1.一个节点最多只有两个子节点,其 ... -
B树温习
2012-01-18 00:36 753B树 即二叉搜索树: 1 ... -
Linux下tar命令详解
2012-01-16 11:09 858tar [-cxtzjvfpPN] 文件与目录 .... ... -
linux--tail
2012-01-12 21:49 914用途(主要用来查看日志) 从指定点开始将文件写到 ... -
查看linux版本
2012-01-12 21:33 866有以下命令可以查看:# lsb_release -aLS ... -
PS命令详解
2012-01-12 21:27 1005... -
vim编辑器之删除
2012-01-05 19:03 1577vim编辑器之删除: x 删除光标下的字符 (&q ... -
linux之ps命令
2012-01-05 19:00 983平时linux进程查看还是比较常用的,在此研究一下linu ...
相关推荐
### 深入解析JVM:Java虚拟机的精髓与挑战 #### JVM概览与重要性 JVM,即Java Virtual Machine(Java虚拟机),是Java程序员必须掌握的核心技术之一。初学者通常从简单的“HelloWorld”程序开始,逐渐接触更复杂的...
标题中提到了JVM原理、JVM调优、JVM内存模型和JAVA并发,这些都是Java虚拟机(JVM)相关的核心概念。JVM是运行Java字节码的虚拟计算机,为Java提供了一个跨平台的环境,确保Java程序可以在不同的操作系统上运行而...
Java虚拟机(JVM)是Java程序运行的核心,它负责解释和执行字节码,为Java应用程序提供了一个跨平台的运行环境。JDK(Java Development Kit)包含了开发和运行Java程序所需的所有工具,包括JVM。当我们谈论"jdk,jvm...
### JVM参数配置详解 #### 一、理解JVM参数配置的重要性 Java Virtual Machine (JVM) 是运行Java程序的核心环境,其性能优化很大程度上依赖于正确的JVM参数配置。合理配置JVM参数不仅可以显著提升应用程序的运行...
Java虚拟机(JVM)是Java程序运行的基础,它是一个抽象的计算机系统,负责执行Java字节码。本文将深入探讨JVM的启动过程及其基本原理。 首先,我们需要理解JVM的基本概念。JVM是Java Virtual Machine的缩写,它是...
在这个压缩包中,"JVM图解.png"可能是对JVM内部结构的可视化表示,"JVM图解"可能是一个详细的文档,解释了JVM的工作原理,而"JVM指令手册 中文版"则提供了JVM可执行的所有指令的详细信息。下面,我们将深入探讨JVM的...
### JVM 详细介绍:掌握 JVM 的各个组成部分与功能 #### 一、Java 源文件编译及执行 Java 应用程序的核心在于源文件的编译与执行。不同于 C/C++ 这类需要针对不同平台进行编译的语言,Java 采用了一种更为灵活的...
JVM(Java Virtual Machine,Java虚拟机)是运行所有Java程序的假想计算机,是Java程序的运行环境,负责执行指令、管理数据、内存、寄存器等,是实现Java跨平台特性的关键部分。JVM指令手册详细记录了JVM的所有操作...
Java虚拟机(JVM)是Java程序运行的核心组件,它负责解释和执行字节码,为开发者提供了跨平台的运行环境。"jvm视频及笔记"这个资源显然是一份全面学习JVM的材料,结合了视频教程和书面笔记,帮助学习者深入理解JVM的...
【jvm-mon基于控制台的JVM监视】 `jvm-mon`是一款实用的工具,它允许开发者通过控制台界面实时监控Java虚拟机(JVM)的状态。在Java开发过程中,性能分析是至关重要的,因为良好的性能能提升用户体验,降低服务器...
46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT详解JVM,46页PPT...
### JVM必知必会知识点梳理 #### 1. JVM的定义与层次 Java虚拟机(JVM)具有多重含义: - **一套规范**:即Java虚拟机规范,定义了Java虚拟机应该具有的行为。 - **一种实现**:例如HotSpot、J9、JRockit,它们都是...
【狂神说JVM探究】是一份集合了多种格式的学习资料,主要涵盖了Java虚拟机(JVM)的基础知识。这份资料出自B站上的【狂神说Java】系列教程,为快速入门JVM提供了详实的笔记。以下是根据这些资源可能包含的一些关键...
JVM 输出 GC 日志导致 JVM 卡住 JVM 输出 GC 日志导致 JVM 卡住是一个常见的问题,尤其是在高并发和高性能应用中。这个问题的根源在于 JVM 的垃圾回收机制(Garbage Collection,GC),它会在 JVM 运行时周期性地...
Java虚拟机(JVM)是Java程序运行的基础,它...通过阅读《JVM详解.pdf》、《java内存模型.pdf》、《慢慢琢磨jvm.pdf》和《JVM调优总结.pdf》,我们可以更全面地掌握JVM的工作原理,提升我们的Java编程和系统调优能力。
在Java开发领域,JVM(Java Virtual Machine)是运行所有Java程序的核心,它负责解析字节码并执行程序。深入理解JVM的内核原理、诊断技巧以及优化方法对于提升应用性能至关重要。本教程——“深入JVM内核—原理、...
JVM(Java虚拟机)是Java语言运行的基础,它负责执行Java字节码,并且是Java跨平台特性的关键实现。JVM的主要职责包括加载Java程序、验证字节码、将字节码转换成机器码执行、内存管理、垃圾回收和提供安全机制等。...
Java虚拟机(JVM)是Java编程语言的核心组成部分,它为Java程序提供了运行环境,使得Java代码能够在不同的操作系统上“一次编写,到处运行”。JVM是Java平台的一部分,负责执行字节码,管理内存,垃圾收集,以及提供...
说明:kubernetes集群监控jvm内存监控模板
"浅谈 JVM 原理" JVM(Java Virtual Machine)是一种虚拟机,它可以模拟完整的硬件系统功能,运行在一个完全隔离的环境中,提供了一个完整的计算机系统。JVM 可以分为三类:VMWare、Visual Box 和 JVM。其中,...