首页 | 联系我们 | 叶凡网络官方QQ群:323842844
游客,欢迎您! 请登录 免费注册 忘记密码
您所在的位置:首页 > 新闻中心 > 行业新闻 > 正文

名扬互联:JVM的内存结构和6大区域

作者:cocomyyz 来源: 日期:2014-1-27 11:09:38 人气:0 加入收藏 评论:0 标签:

接下来看看JVM如何做到自动的对象内存回收的这里指的Heap以及MethodArea回收,掌握了JVM对象内存分配的机制后。其他几个区域的回收都由JVM简单的按生命周期来进行管理

算是CPU与计算机打交道最频繁的区域,其实对于我一般理解的计算机内存。所有数据都是先经过硬盘至内存,然后由CPU再从内存中获取数据进行处置,又将数据保存到内存,通过分页或分片技术将内存中的数据再flush至硬盘。那JVM内存结构到底是如何呢?JVM做为一个运行在操作系统上,但又独立于os运行的平台,内存至少应该包括象寄存器、堆栈等区域。

PCRegistPC寄存器)

主要作用是记录当前线程所执行的字节码的行号。字节码解释器工作时就是通过改变当前线程的顺序计数器选取下一条字节码指令来工作的任何分支,PC寄存器是一块很小的内存区域。循环,方法调用,判断,异常处置,线程等待以及恢复线程,递归等等都是通过这个计数器来完成的

处置器的一个内核只会执行一条线程中的指令。因此为了线程等待结束需要恢复到正确的位置执行,由于Java多线程是通过交替线程轮流切换并分配处理器时间的方式来实现的任何一个确定的时间里。每条线程都会有一个独立的顺序计数器来记录当前指令的行号。计数器之间相互独立互不影响,称这块内存为“线程私有”内存。

如果所调用的方法为nativ则PC寄存器中不存储任何信息。

l JVM栈

JVM栈中存放的为当前线程中局部基本类型的变量(java中定义的八种基本类型:booleancharbyteshortintlongfloatdoubl局部的返回结果以及StackFrame非基本类型的对象在JVM栈上仅存放一个指向堆上的地址,JVM栈是线程私有的每个线程创建的同时都会创立JVM栈。因此Java中基本类型的变量是值传递,而非基本类型的变量是引用传送,Sun          JDK实现中JVM栈的空间是物理内存上分配的而不是从堆上分配。

并且当线程运行完毕后,由于JVM栈是线程私有的因此其在内存分配上非常高效。这些内存也就被自动回收。

会抛出StackOverflowError错误,当JVM栈的空间缺乏时。SunJDK中可以通过-Xss来指定栈的大小,例如如下代码:

newThreadnewRunnabl{

         publicvoidrun{

            loop0;

         }      

         privatvoidloopinti{

            ifi!=1000{

                i++;

loopi;

            }

            else{

                return;

            }

         }

        }.start;

当JVM参数设置为-Xss1K运行后会报出类似下面的错误:

Exceptioninthread"Thread-0"java.lang.StackOverflowError

l 堆(Heap

JVM用来存储对象实例以及数组值的区域,Heap大家最为熟悉的区域。可以认为Java中所有通过new创立的对象的内存都在此分配,Heap中的对象的内存需要等待GC进行回收,Heap32位的操作系统上最大为2G64位的操作系统上则没有限制,其大小通过-Xm和-Xmx来控制,-Xm为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1G-Xmx为JVM可申请的最大Heap内存,默认为物理内存的1/4默认当空余堆内存小于40%时,JVM会增大Heap大小到-Xmx指定的大小,可通过-XX:MinHeapFreeRatio=来指定这个比例,当空余堆内存大于70%时,JVM会将Heap大小往-Xm指定的大小调整,可通过-XX:MaxHeapFreeRatio=来指定这个比例,但对于运行系统而言,为了防止频繁的HeapSize大小,通常都会将-Xm和-Xmx值设成一样,因此这两个用于调整比例的参数通常是没用的其实jvm中对于堆内存的分配、使用、管理、收集等有更为精巧的设计,具体可以在JVM堆内存分析中进行详细介绍。

会抛出OutOfMemori错误信息。当堆中需要使用的内存逾越其允许的大小时。

l 方法区域(MethodA rea

当开发人员在顺序中通过Class对象中的getNamisInterfac等方法来获取信息时,方法区域存放了所加载的类的信息(名称、修饰符等)类中的静态变量、类中定义为final类型的常量、类中的Field信息、类中的方法信息。这些数据都来源于方法区域,可见方法区域的重要性。同样,方法区域也是全局共享的虚拟机启动时在一定的条件下它也会被GC当方法区域需要使用的内存逾越其允许的大小时,会抛出OutOfMemori错误信息。

默认为64M可通过-XX:PermSiz以及-XX:MaxPermS来指定其大小。SunJDK中这块区域对应的为PermanetGener又称为耐久代。

l 运行时常量池(RuntimeConstPool

存放的为类中的固定的常量信息、方法和Field引用信息等,类似C中的符号表。其空间从方法区域中分配。类或接口的常量池在该类的class文件被java虚拟机胜利装载时分配。

l 外地方法堆栈(NativeMethodStack

此区域用于存储每个nativ方法调用的状态。JVM采用外地方法堆栈来支持nativ方法的执行。

例如有这么一段代码:

publicclassA{

                 publicstaticvoidmainString[]arg{

         Stringa="a";

        Stringb="b";

         Stringab="ab";

         System.out.printlna+b==ab;      //fals

         System.out.println"a"+"b"==ab;  //true

         finalStringafinal="a";

         Stringresult=afinal+"b";

         System.out.printlnresult==ab;     //true

         Stringplus=a+"b";

         System.out.printlnplus==ab;       //fals

           System.out.printlnplus.intern==ab; //true

  }

}

可通过javap–verbosA来辅助理解分析。分析下上面代码执行的结果。

l a+b==ab

需要到运行时才干确定其值,a+b两个变量相加。运行时后JVM会为两者相加后发生一个新的对象,因此a+b==ab结果为fals

l a+b==ab

编译时JVM已经将其变为”ab字符串了而ab=ab也是常量,a+b常量。这两者在常量池即为同一地址,因此(a+b==ab为true

l result==ab

result编译时也已经被转变为了ab和”ab常量池中同样为同一地址,result=afinal+bafin个final变量。因此result==ab为true

l plus=ab

plu和a+b情况是相同的因此plus==ab为fals

l plus.intern==ab

这个方法的作用是获取plu指向的常量池地址,这里的不同点在于调用了plus.intern方法。因此plus.intern==ab为true


本文网址:http://www.mingyangnet.com/html/hangye/1797.html
读完这篇文章后,您心情如何?
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
  • 0
更多>>网友评论
发表评论
编辑推荐
  • 没有资料