Java虚拟机浅探
- 简介
对于java开发人员了来说,对java虚拟机肯定有着或多或少的了解。因为有了虚拟机的存在,才会使得java的内存管理变得那么方便,不再像C++那样使用new/delete来直接管理内存。知名的java虚拟机有:Sun Classic/Exact VM(第一款商用虚拟机,已退役)、Sun HotSpot VM(最常用)、IBM J9 VM、Apache Harmony、Mircrosoft JVM等。了解虚拟机的机制和规则,对大型服务器的管理和开发都具有重要意义。
- 初步研读总结

如图虚拟机的大致构成如上图,虚拟机通常由方法区,虚拟机栈,本地方法栈,堆和程序计数器构成。
程序计数器:程序计数器可以看成是当前线程所执行的字节码的行号指示器,也就是类似取址寄存器,解释器会取得它的值来执行下一条代码的指令。它只占很小的一块内存,通常是可以忽略的。
java虚拟机栈:这块内存是线程私有的,生命周期和线程的生命周期是一致的。它描述的是运行时方法的模型,每个方法会创建一个栈帧,存储局部变量、操作数栈、动态链接、方法出口等信息。
本地方法栈:java包中有部分方法带有native关键字,它的描述大致和虚拟机栈是差不多的,只不过面对的是native方法。
java堆:它是线程共享的一块资源,算是内存中最大的一块,存储大多数的对象实例,也就是new出来的那些。这块区域通常分为eden、新生代、老年代。当堆无法分配内存的时候就会产生:OOM(out of memory)异常。
方法区:和java堆有着差不多的特质,是各个线程共享的内存区,但是这个内存区(在HotSpot上)不会被GC(也成为永久代)。
运行时常量池:它是方法区的一部分,存储编译时期生成的各种字面量和符号引用。
对象的创建:入门的时候hello world写的大致是Hello h = new Hello();这个new的指令就是产生一个对象,也就是在java堆中申请一个内存。一般虚拟机会先检查常量池中是否存在这个对象的引用、该类是否被解析加载过,如果没有则执行相应的类加载过程。java堆中内存是一块规划好的内存,它的两种规划方式是指针碰撞(Bump the Pointer)和空闲列表(Free List)。指针碰撞是内存化为使用过的内存和未使用的内存,中间用指针来隔绝,这是防止内存泄漏的手段(若A在申请内存的时候B没来得及释放,A分配到了B的内存就会引起内存泄漏);空闲列表就是使用一个列表记录内存中尚未被使用的内存,也是一种防止内存泄漏的机制。内存分配完成之后就会把分配到的内存初始化为0值,所以我们申请的类的字段通常默认都是0.
对象的访问定位:第一种方式是通过java栈中的reference来指向堆中对象句柄的部分,句柄管理着具体的对象实例的内存,还有存在常量池的java数据类型;第二种方式是直接不用句柄,reference指向的是堆内存的具体对象位置。


- 实例分析
打开eclipse,偏好设置,preferences的java下的install jres,设置内存的下限和上限

写一个语句来看看内存是否设置成功

当前堆内存的kb数,经过计算略小于32m一点,说明设置成功了。
接下来我们写一段程序

从结果来看,申请了273485个对象之后产生了内存溢出的异常,并且提示的是heap space。这说明了堆内存溢出。一般这种异常在程序中处理优化的思路就是,检查是否有无用对象存活过久没有gc、提高虚拟机内存的限制。
除了堆内存的溢出之外,方法栈和虚拟机栈也会有溢出的异常。它们的溢出分为两种,一种是扩展时候申请内存不足则会抛出OOM,另一种是栈空间不足就会有stackoverflowerror,事实我只能测试出后者。我通过实验方法探究出栈深度大概在18000这样的深度,配合堆内存来估计的话,这个栈深度也不会少于2000,对于大型系统来说,除非死循环递归不然应该不会超过这个深度,如果存在这个异常,一是调整程序,二是提高虚拟机的内存。

接下来我们继续实验,通过创建线程让内存溢出。

它的提示是,unable to create new native thread,表示本地方法栈已经溢出。这样的错误只能去优化你的程序了。
java程序员最熟悉的常量池使用就是String.intern()了,它是检查常量池是否存在,存在就返回这个字符串的引用,不然就创建这个字符串在常量池并返回引用。
常量池溢出我一直没测试出来,不知道是不是1.8的新特性。

书上还有PermGen space和本机内存溢出等,至此初步了解了java内存的基本结构和一些常见错误的产生和处理思路,对虚拟机的理解也加深了。
- 参考
《深入理解Java虚拟机(第二版)》 第二章
Java虚拟机浅探的更多相关文章
- 【Java虚拟机】浅谈Java虚拟机
跨平台 Java的一大特性是跨平台,而Java是如何做到跨平台的呢? 主要依赖Java虚拟机,具体来说,是Java虚拟机在各平台上的实现. Java虚拟机在不同的平台有不同的实现.同一份字节码,通过运 ...
- 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位
参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...
- 浅谈java虚拟机|系列1|架构简介
今天开了一个专题.谈谈我们java程序员每天面对的java虚拟机(jvm). 本质上来说,jvm分两部分:编译器(compiler)和运行时(runtime). 所谓的编译器,简单来说,他就是个翻译机 ...
- 深入理解Java虚拟机-第1章-走进Java-读书笔记
第 1 章 走近 Java 前言 Java 的技术体系主要是由支撑 Java 程序运行的虚拟机.为各开发领域提供接口支持的 Java API.Java 编程语言及许许多多的第三方 Java 框架(如 ...
- 一文了解JAVA虚拟机的重要组成
JVM是JAVA平台的重要组成之一,因涉及知识点太多,故从以下几个方面对JVM进行浅层面的介绍,如果需要深入理解,推荐学习机械工业出版社的<深入理解JAVA虚拟机>. 请尊重作者劳动成果, ...
- 编译你的第一个Java虚拟机--Centos 7 编译openJdk1.7源码
一.前言 最近在看<深入java虚拟机>,看完后,打算自己实际编译一个jvm出来看看,实践一下. 书上提到了Oracle JDK和OpenJdk的关系,Oracle Jdk7 和OpenJ ...
- Java虚拟机 - 符号引用和直接引用理解
java -- JVM的符号引用和直接引用 https://www.zhihu.com/question/50258991 在JVM中类加载过程中,在解析阶段,Java虚拟机会把类的二级制数据中的符号 ...
- 深入理解Java虚拟机---类加载机制(简略版)
类加载机制 谈起类加载机制,在这里说个题外话,当初本人在学了两三个月的Java后,只了解了一些皮毛知识,就屁颠屁颠得去附近学校的招聘会去蹭蹭面试经验,和HR聊了一会后开始了技术面试,前抛出了两个简单的 ...
- 【Java 虚拟机探索之路系列】:JIT编译器
作者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell 为 ...
随机推荐
- Database first with EntityFramework (Migration)安装和升级
最近看了国外几个项目,发现用EntityFramework做Code First的项目现在很流行. 最让我有兴趣的一个功能则是,EntityFramework对于数据库的安装和升级的无缝完美支持,且很 ...
- 看看C# 6.0中那些语法糖都干了些什么(终结篇)
终于写到终结篇了,整个人像在梦游一样,说完这一篇我得继续写我的js系列啦. 一:带索引的对象初始化器 还是按照江湖老规矩,先扒开看看到底是个什么玩意. 1 static void Main(strin ...
- Windows批处理:请求远程协助
公司办公场地分别在两个不同的楼层,处理问题要来回跑,所以思考使用远程访问的方式解决问题.同事大多对电脑不熟悉,使用「通讯软件」和「电话」教同事开启远程桌面沟通成本挺高,另外公司IP地址.账号密码都没统 ...
- jquery $.each终止本次循环
1.for循环中我们使用continue:终止本次循环计入下一个循环,使用break终止整个循环. 2.而在jquery中 $.each则对应的使用return true 进入下一个循环,return ...
- List集合的removeAll(Collection<E> col) 和clear方法的区别
//removeAll()方法private static void testList(){ List<String> list = new ArrayList<String> ...
- Bootsrap基本应用
Bootsrap 用法: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...
- Node.js包管理器Yarn的入门介绍与安装
FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT. 就在昨天, Facebook 发布了新的 node.js 包管理器 Yarn 用以替代 npm .咱 ...
- 利用sharding-jdbc分库分表
sharding-jdbc是当当开源的一款分库分表的数据访问层框架,能对mysql很方便的分库.分表,基本不用修改原有代码,只要配置一下即可,完整的配置参考以下内容: <?xml version ...
- 当div有边框图片的时候,怎么实现内部的p标签的水平和垂直居中
<!-- 这里a.png必须是四边的框都有,限制,这个时候做里边文字的居中,首先在这个里边在套一个div悬浮(absolute或者float:left),然后在这个div(必须设宽高和margi ...
- C语言共用体、大小端、枚举
1.共用体和结构体的相同和不同 (1)相同点就是操作语法几乎相同.(2)不同点是本质上的不同.struct是多个独立元素(内存空间)打包在一起:union是一个元素(内存空间)的多种不同解析方式. # ...