JVM可谓是学习JAVA基础中的基础了,但仍有不少同学对JVM概念还是比较模糊,甚至没有听说过,对java的理解也只是在基础语法 层面,本文就将对JVM进行初步介绍,因篇幅所限,只能介绍JVM基础,如需要进一步学习,建议阅读机械工业出版社出版的《深入理解JAVA虚拟机》。

请尊重作者劳动成果,转载请标明原文链接:

   https://www.cnblogs.com/jpcflyer/p/10666099.html

        Java虚拟机规范中规定的JVM如下图所示:
        可以看出,JVM由JVM运行时数据区(图示中蓝色框包含部分)、执行引擎、本地库接口、本地方法库组成。
 
        JVM运行时数据区,分为线程共享部分(方法区、堆)和线程隔离区(虚拟机栈、本地方法栈和程序计数器)。
        1.方法区
         用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
        运行时常量池(Runtime Constant Pool)是方法区的一部分。.Class文件中除了有类的版本/字段/方法/接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将类在加载后进入方法区的运行时常量池中存放.
运行时常量区的内容并不只是在编译期间产生,通过String.intern()也可以实现在运行时向常量区中添加内容。
        需要注意的是:从JDK8开始,方法区被元数据区替代了。具体的原因和两者的区别可以参考官网。
 
        2.堆
        是JVM中最大的一块内存区域,该区域的目的只是用于存储对象实例及数组。该区域也是GC的最主要区域。
        根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样.在实现时,既可以实现固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制).如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,就会抛出OutOfMemoryError异常。
 
        3.虚拟机栈
        每个线程方法在执行时都会创建一个栈帧,包含局部变量表、返回地址、操作数栈等信息。每个方法的执行与完成就对应的栈帧的入栈与出栈过程 。局部变量表占用空间的大小在编译期就确定了。这里需要注意:如果线程请求的栈深度大于虚拟机所允许的深度,将会抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时将会抛出OutOfMemoryError异常。
 
        4.本地方法栈
        与虚拟机栈类似,不过其中执行是本地方法。对于HotSpot虚拟机而言,本地方法栈和虚拟机栈是统一的。
 
        5.程序计数器
       是一个小的内存空间,如果线程正在执行的是一个java方法,则此内存区域记录正在执行的虚拟机字节码指令的地址;如果线程正在执行的是native方法,则计算器中的值为空。此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
 
        这几部分都有相关的JDK自带工具可以分析查看,比如jps, jstack, jmap, jhat, jstat等,还有图形化工具jconsole,jvisualvm,但对于Linux服务器就无能为力了。
 
        好了,关于JVM就讲完了,接下来进行提问:JVM哪些区域会发生OOME,以及各自原因是什么?
 
        堆内存不足是最常见的 OOM 原因之一,抛出的错误信息是“java.lang.OutOfMemoryError:Java heap space”,原因可能千奇百怪,例如,可能存在内存泄漏问题;也很有可能就是堆的大小不合理,比如我们要处理比较可观的数据量,但是没有显式指定 JVM 堆大小或者指定数值偏小;或者出现 JVM 处理引用不及时,导致堆积起来,内存无法释放等。
        而对于 Java 虚拟机栈和本地方法栈,这里要稍微复杂一点。如果我们写一段程序不断的进行递归调用,而且没有退出条件,就会导致不断地进行压栈。类似这种情况,JVM 实际会抛出 StackOverFlowError;当然,如果 JVM 试图去扩展栈空间的的时候失败,则会抛出 OutOfMemoryError。
        对于老版本的 Oracle JDK,因为永久代的大小是有限的,并且 JVM 对永久代垃圾回收(如,常量池回收、卸载不再需要的类型)非常不积极,所以当我们不断添加新类型的时候,永久代出现 OutOfMemoryError 也非常多见,尤其是在运行时存在大量动态类型生成的场合;类似 Intern 字符串缓存占用太多空间,也会导致 OOM 问题。对应的异常信息,会标记出来和永久代相关:“java.lang.OutOfMemoryError: PermGen space”。
        随着元数据区的引入,方法区内存已经不再那么窘迫,所以相应的 OOM 有所改观,出现 OOM,异常信息则变成了:“java.lang.OutOfMemoryError: Metaspace”。
        直接内存不足,也会导致 OOM。
 
        后记:
        JVM是JAVA面试过程中最容易被问到的基础题目,在本篇JVM介绍完后,后面还准备了更多有意思的JAVA基础面试题,这些将作为提升JAVA基础能力的免费系列课程,从面试题出发,对每个问题举一反三,以点带面,不做不求甚解之人,最终目标不是学会答题,而是学会题目本身涉及到的所有知识点。暂定的全部面试题目课程包含如下内容:
        谈谈你对JVM的理解?
        final,finally,finalize有什么区别?
        String,StringBuffer,StringBuilder有什么区别?
        Exception和Error有什么区别?
        Hashtable,HashMap,TreeMap有什么区别?
        Vector,ArrayList,LinkedList有什么区别?
        int和Integer有什么区别?
        接口和抽象类有什么区别?
        如何保证集合是线程安全的?
        谈谈你知道的设计模式?
 
        搜索关注微信公众号“程序员姜小白”,获取更新精彩内容哦。
 

谈谈对JVM的理解的更多相关文章

  1. JVM如何理解Java泛型类(转)

    一个很典型的泛型(generic)代码.T是类型变量,可以是任何引用类型: public class Pair<T>{ private T first=null; private T se ...

  2. JVM如何理解Java泛型类

    //泛型代码 public class Pair<T>{ private T first=null; private T second=null; public Pair(T fir,T  ...

  3. JVM深入理解

    JVM深入理解 一.JVM介绍 JVM应用百度百科的原话是: JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过 ...

  4. JVM的理解

    1.Java程序是交由JVM执行的,所以我们在谈Java内存区域划分的时候事实上是指JVM内存区域划分.在讨论JVM内存区域划分之前,先来看一下Java程序具体执行的过程: 也相当与 注:JVM(ja ...

  5. 谈谈对XML的理解?说明Web应用中Web.xml文件的作用?

    谈谈对XML的理解?说明Web应用中Web.xml文件的作用? 解答:XML(Extensible Markup Language)即可扩展标记语言,它与HTML一样,都是SGML(Standard ...

  6. 12.谈谈this对象的理解

    1.谈谈this对象的理解? 2.this指向问题   Javascript理解this对象 this是函数运行时自动生成的一个内部对象,只能在函数内部使用,但总指向调用它的对象. 通过以下几个例子加 ...

  7. [转帖]JVM—深入理解内存模型与垃圾收集机制

    JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...

  8. Java 中级 学习笔记 1 JVM的理解以及新生代GC处理流程

    写在最前 从毕业到现在已经过去了差不多一年的时间,工作还算顺利,但总是离不开CRUD ,我觉得这样下去肯定是不行的,温水煮青蛙,势必有一天,会昏昏沉沉的迷失在温水里.所以,需要将之前学习JAVA 当中 ...

  9. jvm优化理解

    jvm架构理解 jvm程序执行流程 编译器和解释器协调工作流程 在部分商用虚拟机中(如HotSpot),java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或者某段代码执行的特别频繁后就会 ...

随机推荐

  1. JavaSE基础知识(3)—流程控制结构

    一.顺序结构 1.说明 程序从上往下依次执行,中间没有任何跳转或选择2.特点 变量必须遵循 “前向引用” (局部变量必须先声明.赋值,然后再使用!) 二.分支结构(条件) 1.说明 程序从两条或多条路 ...

  2. centos 7 安装python 3.x

    首先 安装一些 可能需要的依赖: yum -y groupinstall "Development tools" yum -y install zlib-devel bzip2-d ...

  3. 6L - 大菲波数

    Fibonacci数列,定义如下: f(1)=f(2)=1 f(n)=f(n-1)+f(n-2) n>=3. 计算第n项Fibonacci数值.  Input 输入第一行为一个整数N,接下来N行 ...

  4. 小程序css--view标签下英文不换行,中文会自动换行

    英文且没有空格不会自动换行,中文或者有空格的英文会自动换行 这种情况在css中添加 : word-break: break-all;\   就可以解决

  5. 201621123002《JAVA程序设计》第四周学习总结

    1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 继承 多态 覆盖 抽象 重载 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需要出现过多的字. 1.3 可选: ...

  6. ulogd(一)

    参考资料: https://blog.csdn.net/eydwyz/article/details/52456335 https://blog.csdn.net/chinalinuxzend/art ...

  7. docker日志设置定期清理

    1.新建/etc/docker/daemon.json,若有就不用新建了 2.添加log-dirver和log-opts参数,样例如下 "log-driver":"jso ...

  8. C++静态库与动态库(比较透彻)

    这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一本书<程序员的自 ...

  9. python伪装浏览器

    def get_content(url): req_header = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/53 ...

  10. python_day1 条件语句

    一  流程控制 1.if....else 语句 用法: if  条件: 满足条件执行代码 else: if 条件不满足执行此部分代码 例: a = 10 b = 20 if  a>b : pri ...