• 简介

   对于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虚拟机浅探的更多相关文章

  1. 【Java虚拟机】浅谈Java虚拟机

    跨平台 Java的一大特性是跨平台,而Java是如何做到跨平台的呢? 主要依赖Java虚拟机,具体来说,是Java虚拟机在各平台上的实现. Java虚拟机在不同的平台有不同的实现.同一份字节码,通过运 ...

  2. 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位

    参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...

  3. 浅谈java虚拟机|系列1|架构简介

    今天开了一个专题.谈谈我们java程序员每天面对的java虚拟机(jvm). 本质上来说,jvm分两部分:编译器(compiler)和运行时(runtime). 所谓的编译器,简单来说,他就是个翻译机 ...

  4. 深入理解Java虚拟机-第1章-走进Java-读书笔记

    第 1 章 走近 Java 前言 Java 的技术体系主要是由支撑 Java 程序运行的虚拟机.为各开发领域提供接口支持的 Java API.Java 编程语言及许许多多的第三方 Java 框架(如 ...

  5. 一文了解JAVA虚拟机的重要组成

    JVM是JAVA平台的重要组成之一,因涉及知识点太多,故从以下几个方面对JVM进行浅层面的介绍,如果需要深入理解,推荐学习机械工业出版社的<深入理解JAVA虚拟机>. 请尊重作者劳动成果, ...

  6. 编译你的第一个Java虚拟机--Centos 7 编译openJdk1.7源码

    一.前言 最近在看<深入java虚拟机>,看完后,打算自己实际编译一个jvm出来看看,实践一下. 书上提到了Oracle JDK和OpenJdk的关系,Oracle Jdk7 和OpenJ ...

  7. Java虚拟机 - 符号引用和直接引用理解

    java -- JVM的符号引用和直接引用 https://www.zhihu.com/question/50258991 在JVM中类加载过程中,在解析阶段,Java虚拟机会把类的二级制数据中的符号 ...

  8. 深入理解Java虚拟机---类加载机制(简略版)

    类加载机制 谈起类加载机制,在这里说个题外话,当初本人在学了两三个月的Java后,只了解了一些皮毛知识,就屁颠屁颠得去附近学校的招聘会去蹭蹭面试经验,和HR聊了一会后开始了技术面试,前抛出了两个简单的 ...

  9. 【Java 虚拟机探索之路系列】:JIT编译器

    作者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell 为 ...

随机推荐

  1. Android 自带后退按钮的使用

    一.后退按钮有两种定义,分别是向上按钮和返回按钮:向上按钮:偏向于一种父子关系:返回按钮:反映的是一种前后关系 向上按钮:在清单文件中需要添加后退功能按钮的Activity中添加parentActiv ...

  2. JavaScript标准参考教材(alpha)--笔记

    一.导论 二.基本语法 1.严格来说var a=1与a=1效果不太一样,delete命令无法删除前者. JavaScirpt是一种动态类型语言,也就是说,变量的类型没有限制,可以赋予各种类型的值. J ...

  3. Atitit.工作流 与 规则引擎

    Atitit.工作流 与 规则引擎 1.1. 应用来说,通常分为三部分:界面.业务逻辑和存储1 1.2. 自定义操作系列1 1.3. 自定义按钮系列2 1.1. 应用来说,通常分为三部分:界面.业务逻 ...

  4. 简历生成平台项目开发-STEP2问卷调查结果统计分析

    根据之前设计的调查问卷,截止目前为止,一共收到64份问卷结果.一共16题,分别从基本信息.是否对简历制作有需要.对产品期望的特点和建议采纳四个方面设计问题.下面逐题分析问卷结果: 1.您的性别 可以看 ...

  5. VS2015调试时没有启动IIS Express Web服务器 或者停止调试时 IIS Express 跟着关闭

    解决方法: 打开 解决方案资源管理器 -> 点选 Web 项目选择 -> 属性 -> Web "服务器"  去掉勾选"将服务器设置应道所有用户" ...

  6. ajax请求成功后打开新开窗口(window.open())被拦截的解决方法

    问题:今天在做项目时需要在ajax请求成功后打开一个新的窗口,此时遇到浏览拦截了新窗口的问题,尝试在ajax 回调函数中模拟执行 click 或者 submit 等用户行为(trigger('clic ...

  7. 基于面向对象的图片轮播(js原生代码)

    无论你想走多远,你都需要不断地走下去.前端最精华的便是原生的js,这也是我们前端工程师的技术分层的重要指标,也提现这你的代码能力,开发的水平.废话不多说,进入今天的主要分享————基于面向对象思想的图 ...

  8. excel基本

    1,换行:control+option(alt)+enter

  9. Oracle 判断某個字段的值是不是数字

    转:https://my.oschina.net/bairrfhoinn/blog/207835 摘要: 壹共有三种方法,分别是使用 to_number().regexp_like() 和 trans ...

  10. web 前端常用组件【07】弹出层 Layer

    web 项目中总是需要弹出框,来让用户进行下一步的操作. 大到弹出另外一个页面,小到弹出提示.确认等. 经手几个项目,还是感觉 Layer 用起来比较的轻松,你能想到的 Layer 都能帮你做到. 感 ...