• JVM 内存解析,以及自己的一些见解


    Java虚拟机所管理的内存将会包括以下几个运行时数据区域

    程序计数器( Program Counter Register)
    首先程序计数器是一块机比较小的存储空间,也是当前线程私有的一段存储空间,用于记录当前线程执行代码的行数,通俗来讲一个线程会有一个程序计数器,来控制代码运行到了哪一行,字节码解释器工作的时候,就是告诉程序计数器下一条指令执行哪一行的代码,从而控制了,分支(swtich),循环(while),异常(exception),判断(if ),跳转(goto),线程恢复的功能。
    java 虚拟机栈( Java Virtual Machine Stacks)
    java虚拟机栈也是线程私有的,即一个线程会有一个虚拟机栈,其描述的是java虚拟机需要执行的方法。为每一个方法都创建了一个栈(stack fream),其包含了, 局部变量表、 操作数栈、 动态链接、 方法出口,等信息。 每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出,栈的过程。其中局部变量表存放了,各种基本类型数据,以及引用类型数据的地址(指针,代表一个对象的句柄,一条字节码指令的地址),后面会详细解释java虚拟机栈内的具体信息。
    对这个区域规定了两种异常状况:如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;如果虚拟机栈可以动态扩展(当前大部分的Java虚拟机都可动态扩展,只不过Java虚拟机规范中也允许固定长度的虚拟机栈),如果扩展时无法申请到足够的内存,就会抛出outOfMemoryError异常
    本地方法栈( Native Method Stack)
    为什么要有本地方法?
    java 有的时候需要和外系统进行交互,如果外系统不是使用java进行实现的话,就很难进行交互,java有的时候还需要和系统底层的一些硬件打交道,所以就出现了本地方法栈。
    本地方法如何定义?
    简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数。
       "A native method is a Java method whose implementation is provided by non-java code."
       在定义一个native method时,并不提供实现体(有些像定义一个java interface),因为其实现体是由非java语言在外面实现的。下面给了一个示例:    
        public class IHaveNatives
        {
          native public void Native1( int x ) ;
          native static public long Native2() ;
          native synchronized private float Native3( Object o ) ;
          native void Native4( int[] ary ) throws Exception ;
        } 
    其实本地方法栈的功能和虚拟机栈的功能类似,同事也是线程私有,也是存储当前执行的所有方法和函数执行的信息。同样本地方法栈也会抛出StackOverflowError和outOfMemoryError异常信息。
    Java堆(Java Heap)
    java堆是内存当中最大的一块,里面存储了对象的信息,被所有线程所共享的一片内存区域。在虚拟机规范当中是这样定义的: 所有的对象实例以及数组都要在堆上分配,但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、 标量替换优化技术将会导致一些微妙的变化发生,所有的对象都
    分配在堆上也渐渐变得不是那么“绝对”了。
    GC操作就发生在这个区域,主要分成新生代和老生代,如果再详细划分, Eden空间、 From Survivor空间、 To Survivor空间等。在这个线程共享的区域,可能会划分出线程的缓冲区,不过再怎么去进行划分,都是为了能够管理这个空间,做好垃圾的回收工作。
    根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。 在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。 如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
    方法区(Method Area)
    方法区是线程共享的一段区域, 它用于存储已被虚拟机加载的类信息、 常量、 静态变量、 即时编译器编译后的代码等数据。
     
    通过自己的理解我把图化成了如下的样子

    欢迎关注我的微信公众号 “我是一个假的程序猿”

    分享生活,技术,程序猿养生(我是认真的),以及程序猿招聘(欢迎程序猿关注),HR招聘信息发送(欢迎HR投稿)。

  • 相关阅读:
    php生成二维码
    赞的算法
    Linux系统信息查看命令大全
    详细介绍Linux telnet命令的使用
    Linux VSFTP服务器
    禁止浏览器缓存页面的方法
    php开启短标签
    BZOJ2648 SJY摆棋子(KD-Tree)
    KD-Tree学习笔记
    BZOJ5461 PKUWC2018Minimax(概率期望+线段树合并+动态规划)
  • 原文地址:https://www.cnblogs.com/binarysheep/p/9479698.html
Copyright © 2020-2023  润新知