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 为 ...
随机推荐
- 一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为“希赛网”)个人空间发布过一些 ...
- 原创 C++作用域 (一)
1概述 在所有的计算机程序中,一个基本的目标是操作一些数据,然后获得一些结果.为了操作这些数据,需要为这些数据分配一段内存,我们可以将这段内存称为变量.为了方便操作,以及程序可读性方面的考虑,需要使用 ...
- AspNetPager 多条件分页查询
AspNetPager 这个分页控件一般做后台基本都知道的,我就不多说了(说明与下载链接:http://www.webdiyer.com/Controls/AspNetPager),嘿嘿!其实我也是刚 ...
- 简单配置 nginx 反向代理
# Nginx 域名反向代理配置# 安装nginx yum install nginx -y# 修改配置文件 进入配置文件目录 cd /etc/nginx/conf.d 新建配置文件以.conf结尾 ...
- shell两数之间的算术运算
#!/bin/bash read -p "请输入第一个数:" a read -p "请输入第二个数:" b echo "$a+$b=$[$a+$b]& ...
- Linux工具快速教程
看到一linux中常用工具使用教程,非常好.猛击下面的地址 github:https://github.com/me115/linuxtools_rst 在线文档:http://linuxtools- ...
- html框架练习
<html><frameset rows="50,*" ><frame name="main" src="/examp ...
- Referenced file contains errors (http://www.springframework.org/schema...错误
Referenced file contains errors (http://www.springframework.org/schema...错误 Referenced file contains ...
- Eclipse CDT: Shortcut to switch between .h and .cpp
ctrl+ tab is the default shortcut.You can change it in Window → Preferences → General → Keys: Toggl ...
- jQuery插件开发精品教程,让你的jQuery提升一个台阶
要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样,得平台者得天下.苹果,微软,谷歌等巨头,都有各自的平台及生态圈 ...