java内存区域(二)

本文从以下内容介绍java内存区域

一、运行时数据区域

一、运行时数据区域

1、线程与JVM线程

1.1、线程

       此处所说的线程指程序执行过程中的一个线程实体。

       JVM 允许一个应用并发执行多个线程。Hotspot JVM 中的 Java 线程与原生操作系统线程有直接的映射关系。当线程本地存储、缓冲区分配、同步对象、栈、程序计数器等准备好以后,就会创建一个操作系统原生线程。Java 线程结束,原生线程随之被回收。操作系统负责调度所有线程,并把它们分配到任何可用的 CPU 上。当原生线程初始化完毕,就会调用 Java 线程的 run() 方法。run() 返回时,被处理未捕获异常,原生线程将确认由于它的结束是否要终止 JVM 进程(比如这个线程是最后一个非守护线程)。当线程结束时,会释放原生线程和 Java 线程的所有资源。

1.2、JVM线程

        后台线程与触发 public static void main(String[]) 函数的主线程以及主线程创建的其他线程一起运行。Hotspot JVM 后台运行的系统线程主要有下面几个:

虚拟机线程(VM thread) 这个线程等待 JVM 到达安全点操作出现。这些操作必须要在独立的线程里执行,因为当堆修改无法进行时,线程都需要 JVM 位于安全点。这些操作的类型有:stop-the-world 垃圾回收、线程栈 dump、线程暂停、线程偏向锁(biased locking)解除。
周期性任务线程 这线程负责定时器事件(也就是中断),用来调度周期性操作的执行。
GC 线程 这些线程支持 JVM 中不同的垃圾回收活动。
编译器线程 这些线程在运行时将字节码动态编译成本地平台相关的机器码。
信号分发线程 这个线程接收发送到 JVM 的信号并调用适当的 JVM 方法处理。

 2、运行时的数据区域



 

 运行时的数据区域:
(1)线程共享的内存区域:

          堆(GC堆) Heap

          方法区 (Non Heap)Method Area

(2)线程私有的内存区域:

          程序计数器 Program Counter Register

          虚拟机栈 VM stack

          本地方法栈 Native Method stack

 1、程序计数器

       程序计数器:为较小的一片内存区域,它的作用可以看做当前线程所执行字节码的行号指示器。虚拟机的概念模型中,字节码解释器的工作就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程回复功能都需要这个计数器来完成。

       JVM的多线程通过线程轮流切换并分配处理器执行时间的方式实现的,任何确定时刻,单个处理器只会执行一条线程指令。

       线程切换后能回到正确的执行位置,因此每条线程都要一个独立的程序计数器,各个线程互不干扰,因此,程序计数器为线程私有的内存区域。

       线程执行的是一个java方法,则这个计数器记录的是正在执行的VM的字节码指令地址;如果执行的是Native方法,则这个计数器的值为Undefined,该区域为唯一一个在Java VM规范中没有规定任何OutOfMemoryError的区域。

2、Java VM栈

      虚拟机栈为线程私有,它的声明周期与线程相同。

      虚拟机栈描述的是:java方法执行的内存模型,每个方法的执行的时候都会同时创建一个栈帧(stack frame)。

      栈帧:用于存储局部变量表、操作栈、动态链接、方法的出口信息、类当前方法运行时常量池的引用。

      Java VM规范中,该区域有两种异常:

      (1)StackOverflowError:如果线程请求的栈的深度大于虚拟机所允许的深度会抛出该异常;

      (2)OutOfMemoryError:虚拟机栈可以动态扩展,当扩展无法申请到足够的内存时会抛出该异常;

3、本地方法栈

       与java vm栈的功能类似;

       虚拟机栈为虚拟机执行java方法(字节码服务),而本地方法栈则为虚拟机用到的native方法服务;

       本地方法栈同样也会抛出StackOverflowError、OutOfMemoryError异常。

4、Java堆

      VM内存管理中最大的一块区域;

      Java堆为所有的线程共享,在虚拟机启动时创建;

      此区域唯一的目的是存放对象的实例,几乎所有的对象实例都在该区域分配;

      Java堆为垃圾回收器管理的主要区域,因此,该区域与也别成为GC堆。

5、方法区

      与java的堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、及时编译器编译后的代码等数据。该区域的别名叫做Non Heap(非堆),目的与java堆区分。

5.1、运行时常量池

       方法区的一部分;

       Class文件中除了有类的版本、字段、方法、接口等信息描述外,还有一项信息是常量池;

       Class文件中的常量池用于存放编译器生成的各种字面量和符号引用,这部分内容在类加载后存放到方法区的运行时常量池中。

        运行时常量池较之Class文件的常量池另外一个重要特征是具备动态性;

        java语言并不要求常量一定只能在编译期产生,也就是说并非在Class文件中的常量池在类文件加载时进入到方法区的运行时常量池,运行期同样可以讲常量放入到池中,这种特性用的较多的是String类的intern方法;

        运行时常量池为方法区的一部分,自然会受到方法区内存限制,当常量池无法申请到内存时会抛出OutOfMemoryError。



 

 本文参考自:http://www.importnew.com/17770.html 

                       《深入理解Java虚拟机》 周志明

猜你喜欢

转载自1498116590.iteye.com/blog/2409551