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 为 ...
随机推荐
- React Native 之生命周期
前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...
- (八)Eclipse创建Maven项目运行mvn命令
1.Eclipse创建Maven项目 使用Eclipse创建一个Maven项目非常的简单,选择菜单项File>New>Other(也可以在项目结构空白处右击鼠标键),在弹出的对话框中选择M ...
- Cordova开发速记
JS安全问题,已使用MERGES目录对不同的平台进行单独的控制,但需要在主页中引用平台重载文件,如<script src="script/platformOverrides.js&qu ...
- 简历生成平台项目开发-STEP5初步界面demo实现
谭卓因为暑期实习,去杭州实习了,走之前在git上上传了一些文档(https://github.com/USTC-CV-creator/),项目到目前为止,前端demo已经做好,后台接收请求生成PDF部 ...
- 企业号微信支付 公众号支付 H5调起支付API示例代码 JSSDK C# .NET
先看效果 1.本文演示的是微信[企业号]的H5页面微信支付 2.本项目基于开源微信框架WeiXinMPSDK开发:https://github.com/JeffreySu/WeiXinMPSDK 感谢 ...
- 《HeadFirst SQL》笔记
规范化 0 约束 1 原子性 2 第一范式 1NF 3 数据模式 4 依赖 5 联接查询 6 交叉联接(AKA 笛卡尔联接,叉积) 7 内联接 8 子查询 9 外联接 10 自联接 11 集合 12 ...
- linux输入子系统(input subsystem)之evdev.c事件处理过程
1.代码 input_subsys.drv.c 在linux输入子系统(input subsystem)之按键输入和LED控制的基础上有小改动,input_subsys_test.c不变. input ...
- java中可定制的序列化过程 writeObject与readObject
来源于:[http://bluepopopo.iteye.com/blog/486548] 什么是writeObject 和readObject?可定制的序列化过程 这篇文章很直接,简单易懂.尝试着翻 ...
- Linux 文件系统分区基础
文件系统就是管理设备,组织文件的一些结构和算法. /boot分区,它包含了操作系统的内核和在启动系统过程中所要用到的文件, 建这个分 区是有必要的,因为目前大多数的PC机要受到BIOS的限制,况且如果 ...
- MMORPG大型游戏设计与开发(服务器 AI 事件)
AI中的事件与场景中的事件大致相同,都是由特定的条件触发的.只不过AI的事件与其他事件不同的是,对于AI的事件往往是根据不同的AI类型,和动态的触发条件下才产生的.其实不管AI多么智能,它对应的触发条 ...