在讨论JVM内存区域分析之前,先来看一下Java程序详细运行的过程:




-我们今天就来分析一下Java程序运行过程的-Runtime-Data-Area(运行时数据)-这一块" class="headerlink" title="Java 程序的运行过程:Java 源码文件(.Java文件)-> Java Compiler(Java编译器)->Java 字节码文件(.class文件)->类载入器(Class Loader)->Runtime Data Area(运行时数据)-> Execution Engine(运行引擎)。 我们今天就来分析一下Java程序运行过程的 Runtime Data Area(运行时数据) 这一块" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">Java
程序的运行过程:Java 源码文件(.Java文件)-> Java Compiler(Java编译器)->Java 字节码文件(.class文件)->类载入器(Class Loader)->Runtime Data Area(运行时数据)-> Execution Engine(运行引擎)。

我们今天就来分析一下Java程序运行过程的 Runtime
Data Area(执行时数据) 这一块

那么执行时数据区包含哪几部分呢?

  • 程序计数器(Program Counter Register)
  • Java虚拟机栈(VM Stack)
  • 本地方法栈(Native Method Stack)
  • 方法区(method area)
  • 堆(heap)

一、程序计数器

JVM规范中规定。假设线程运行的是非native方法,则程序计数器中保存的是当前须要运行的指令地址,假设线程运行的是native方法,则程序计数器中的值undefined。

每一个线程都有自己独立的程序计数器。为什么呢?由于多线程下,一个CPU内核仅仅会运行一条线程中的指令,因此为了使每一个线程在线程切换之后可以恢复到切换之前的程序运行的位置,所以每一个线程都有自己独立的程序计数器。" style="margin:20px 0px 0px; padding:0px 0px 5px; border-width:0px 0px 1px; border-bottom-style:solid; border-bottom-color:rgb(221,221,221); outline:0px; font-family:Times,Georgia,serif; font-size:16px; vertical-align:baseline; color:rgb(87,76,76); line-height:26.4px">

每一个线程都有自己独立的程序计数器。为什么呢?由于多线程下,一个CPU内核仅仅会运行一条线程中的指令。因此为了使每一个线程在线程切换之后可以恢复到切换之前的程序运行的位置。所以每一个线程都有自己独立的程序计数器。" class="headerlink" title="用来指示程序运行哪一条指令,这跟汇编语言的程序计数器的功能在逻辑上是一样的。

JVM规范中规定,假设线程运行的是非native方法,则程序计数器中保存的是当前须要运行的指令地址,假设线程运行的是native方法,则程序计数器中的值undefined。

每一个线程都有自己独立的程序计数器。为什么呢?由于多线程下,一个CPU内核仅仅会运行一条线程中的指令,因此为了使每一个线程在线程切换之后可以恢复到切换之前的程序运行的位置,所以每一个线程都有自己独立的程序计数器。" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">用来指示程序运行哪一条指令,这跟汇编语言的程序计数器的功能在逻辑上是一样的。JVM规范中规定,假设线程运行的是非native方法,则程序计数器中保存的是当前须要运行的指令地址。假设线程运行的是native方法,则程序计数器中的值undefined。

每一个线程都有自己独立的程序计数器。为什么呢?由于多线程下,一个CPU内核仅仅会运行一条线程中的指令,因此为了使每一个线程在线程切换之后可以恢复到切换之前的程序运行的位置。所以每一个线程都有自己独立的程序计数器。

二、Java虚拟机栈

我们所说的“栈”是指Java虚拟机栈,一个栈帧中包含:局部变量表、操作数栈、动态连接、方法返回地址、附加信息" style="margin:20px 0px 0px; padding:0px 0px 5px; border-width:0px 0px 1px; border-bottom-style:solid; border-bottom-color:rgb(221,221,221); outline:0px; font-family:Times,Georgia,serif; font-size:16px; vertical-align:baseline; color:rgb(87,76,76); line-height:26.4px">
Java虚拟机栈中存放的是一个个栈帧,当程序运行一个方法时。就会创建一个栈帧并压入栈中,当方法运行完成之后,便会将栈帧移除栈。我们所说的“栈”是指Java虚拟机栈,一个栈帧中包含:局部变量表、操作数栈、动态连接、方法返回地址、附加信息

1、局部变量表

在Java虚拟机规范中,对这个区域规定了两种异常状况:假设线程请求的栈深度大于虚拟机所同意的深度,将抛出StackOverflowError异常;假设虚拟机栈能够动态扩展(当前大部分的Java虚拟机都可动态扩展,仅仅只是Java虚拟机规范中也同意固定长度的虚拟机栈)。假设扩展时无法申请到足够的内存。就会抛出OutOfMemoryError异常。

" style="margin:20px 0px 0px; padding:0px 0px 5px; border-width:0px 0px 1px; border-bottom-style:solid; border-bottom-color:rgb(221,221,221); outline:0px; font-family:Times,Georgia,serif; font-size:16px; vertical-align:baseline; color:rgb(87,76,76); line-height:26.4px">

如:各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身。可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其它与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。当中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型仅仅占用1个。局部变量表的大小在编译器就能够确定其大小了。因此在程序运行期间局部变量表的大小是不会改变的。在Java虚拟机规范中。对这个区域规定了两种异常状况:假设线程请求的栈深度大于虚拟机所同意的深度,将抛出StackOverflowError异常;假设虚拟机栈能够动态扩展(当前大部分的Java虚拟机都可动态扩展。仅仅只是Java虚拟机规范中也同意固定长度的虚拟机栈)。假设扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。

" class="headerlink" title="主要是存储方法中的局部变量,包含方法中局部变量的信息和方法的參数。

如:各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其它与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。当中64位长度的long和double类型的数据会占用2个局部变量空间(Slot)。其余的数据类型仅仅占用1个。局部变量表的大小在编译器就能够确定其大小了,因此在程序运行期间局部变量表的大小是不会改变的。在Java虚拟机规范中,对这个区域规定了两种异常状况:假设线程请求的栈深度大于虚拟机所同意的深度,将抛出StackOverflowError异常;假设虚拟机栈能够动态扩展(当前大部分的Java虚拟机都可动态扩展,仅仅只是Java虚拟机规范中也同意固定长度的虚拟机栈),假设扩展时无法申请到足够的内存。就会抛出OutOfMemoryError异常。

" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">主要是存储方法中的局部变量。包含方法中局部变量的信息和方法的參数。

如:各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型,它不等同于对象本身。可能是一个指向对象起始地址的引用指针。也可能是指向一个代表对象的句柄或其它与此对象相关的位置)和returnAddress类型(指向了一条字节码指令的地址)。当中64位长度的long和double类型的数据会占用2个局部变量空间(Slot),其余的数据类型仅仅占用1个。局部变量表的大小在编译器就能够确定其大小了,因此在程序运行期间局部变量表的大小是不会改变的。在Java虚拟机规范中,对这个区域规定了两种异常状况:假设线程请求的栈深度大于虚拟机所同意的深度,将抛出StackOverflowError异常;假设虚拟机栈能够动态扩展(当前大部分的Java虚拟机都可动态扩展,仅仅只是Java虚拟机规范中也同意固定长度的虚拟机栈),假设扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。

操作数栈

" style="margin:20px 0px 0px; padding:0px 0px 5px; border-width:0px 0px 1px; border-bottom-style:solid; border-bottom-color:rgb(221,221,221); outline:0px; font-family:Times,Georgia,serif; font-size:16px; vertical-align:baseline; color:rgb(87,76,76); line-height:26.4px">

" class="headerlink" title="虚拟机把操作数栈作为它的工作区。程序中的全部计算过程都是在借助于操作数栈来完毕的,大多数指令都要从这里弹出数据,运行运算。然后把结果压回操作数栈。

" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">虚拟机把操作数栈作为它的工作区。程序中的全部计算过程都是在借助于操作数栈来完毕的,大多数指令都要从这里弹出数据。运行运算,然后把结果压回操作数栈。

动态连接

每一个栈帧都包括一个指向执行时常量池中该栈帧所属方法的引用(指向执行时常量池:在方法执行的过程中有可能须要用到类中的常量),持有这个引用是为了支持方法调用过程中的动态连接

方法返回地址

" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">当一个方法运行完成之后。要返回之前调用它的地方,因此在栈帧中必须保存一个方法返回地址。

附加信息

在实际开发中,通常会把动态连接,方法返回地址与其他附加信息所有归为一类。称为栈帧信息。

" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">虚拟机规范同意详细的虚拟机实现添加一些规范里没有描写叙述的信息到栈帧中,比如与高度相关的信息,这部分信息全然取决于详细的虚拟机实现。

在实际开发中。通常会把动态连接,方法返回地址与其他附加信息所有归为一类,称为栈帧信息。

三、本地方法栈、

" style="margin:20px 0px 0px; padding:0px 0px 5px; border-width:0px 0px 1px; border-bottom-style:solid; border-bottom-color:rgb(221,221,221); outline:0px; font-family:Times,Georgia,serif; font-size:16px; vertical-align:baseline; color:rgb(87,76,76); line-height:26.4px">

与虚拟机栈一样。本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。" class="headerlink" title="本地方法栈(Native Method Stack)与虚拟机栈所发挥的作用是很相似的,它们之间的差别只是是虚拟机栈为虚拟机运行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。

与虚拟机栈一样。本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">本地方法栈(Native
Method Stack)与虚拟机栈所发挥的作用是很相似的。它们之间的差别只是是虚拟机栈为虚拟机运行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。

与虚拟机栈一样。本地方法栈区域也会抛出StackOverflowError和OutOfMemoryError异常。

四、堆(heap)

那么在Java中是怎么样的呢?Java中的堆是用来存储对象本身的以及数组(当然,数组引用是存放在Java栈中的)。差点儿全部的对象实例都在这里分配内存。在Java中,程序猿基本不用去关心空间释放的问题,Java的垃圾回收机制会自己主动进行处理。另外,堆是被全部线程共享的,在JVM中仅仅有一个堆。" style="margin:20px 0px 0px; padding:0px 0px 5px; border-width:0px 0px 1px; border-bottom-style:solid; border-bottom-color:rgb(221,221,221); outline:0px; font-family:Times,Georgia,serif; font-size:16px; vertical-align:baseline; color:rgb(87,76,76); line-height:26.4px">

那么在Java中是怎么样的呢?Java中的堆是用来存储对象本身的以及数组(当然。数组引用是存放在Java栈中的),差点儿全部的对象实例都在这里分配内存。在Java中。程序猿基本不用去关心空间释放的问题。Java的垃圾回收机制会自己主动进行处理。

另外。堆是被全部线程共享的,在JVM中仅仅有一个堆。" class="headerlink" title="在C语言中,程序猿能够通过malloc函数和free函数在堆上申请和释放空间。

那么在Java中是怎么样的呢?Java中的堆是用来存储对象本身的以及数组(当然,数组引用是存放在Java栈中的),差点儿全部的对象实例都在这里分配内存。在Java中,程序猿基本不用去关心空间释放的问题,Java的垃圾回收机制会自己主动进行处理。

另外,堆是被全部线程共享的。在JVM中仅仅有一个堆。" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">在C语言中。程序猿能够通过malloc函数和free函数在堆上申请和释放空间。

那么在Java中是怎么样的呢?Java中的堆是用来存储对象本身的以及数组(当然。数组引用是存放在Java栈中的),差点儿全部的对象实例都在这里分配内存。在Java中,程序猿基本不用去关心空间释放的问题,Java的垃圾回收机制会自己主动进行处理。

另外,堆是被全部线程共享的。在JVM中仅仅有一个堆。

五、方法区

Class文件里除了有类的版本号、字段、方法、接口等描写叙述信息外,另一项信息是常量池(Constant-Pool-Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类载入后进入方法区的执行时常量池中存放。在JVM规范中,没有强制要求方法区必须实现垃圾回收。非常多人习惯将方法区称为“永久代”,是由于HotSpot虚拟机以永久代来实现方法区。从而JVM的垃圾收集器能够像管理堆区一样管理这部分区域。从而不须要专门为这部分设计垃圾回收机制。

只是自从JDK7之后。Hotspot虚拟机便将执行时常量池从永久代移除了。

" style="margin:20px 0px 0px; padding:0px 0px 5px; border-width:0px 0px 1px; border-bottom-style:solid; border-bottom-color:rgb(221,221,221); outline:0px; font-family:Times,Georgia,serif; font-size:16px; vertical-align:baseline; color:rgb(87,76,76); line-height:26.4px">

只是自从JDK7之后,Hotspot虚拟机便将执行时常量池从永久代移除了。" class="headerlink" title="方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机载入的类信息、常量、静态变量、以及编译器编译后的代码等。

执行时常量池(Runtime Constant Pool)是方法区的一部分。

Class文件里除了有类的版本号、字段、方法、接口等描写叙述信息外,另一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用。这部分内容将在类载入后进入方法区的执行时常量池中存放。

在JVM规范中。没有强制要求方法区必须实现垃圾回收。

非常多人习惯将方法区称为“永久代”,是由于HotSpot虚拟机以永久代来实现方法区,从而JVM的垃圾收集器能够像管理堆区一样管理这部分区域,从而不须要专门为这部分设计垃圾回收机制。只是自从JDK7之后,Hotspot虚拟机便将执行时常量池从永久代移除了。" style="margin:0px; padding:0px; border:0px; outline:none; font-weight:inherit; font-style:inherit; font-family:inherit; vertical-align:baseline; text-decoration:none; color:rgb(37,143,184)">方法区(Method
Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机载入的类信息、常量、静态变量、以及编译器编译后的代码等。执行时常量池(Runtime Constant Pool)是方法区的一部分。

Class文件里除了有类的版本号、字段、方法、接口等描写叙述信息外,另一项信息是常量池(Constant Pool Table)。用于存放编译期生成的各种字面量和符号引用,这部分内容将在类载入后进入方法区的执行时常量池中存放。

在JVM规范中,没有强制要求方法区必须实现垃圾回收。非常多人习惯将方法区称为“永久代”。是由于HotSpot虚拟机以永久代来实现方法区。从而JVM的垃圾收集器能够像管理堆区一样管理这部分区域,从而不须要专门为这部分设计垃圾回收机制。只是自从JDK7之后,Hotspot虚拟机便将执行时常量池从永久代移除了。

注意:native方法是指:指使用
Java 以外的其它语言编写的方法

深入了解Java之虚拟机内存的更多相关文章

  1. Java获取虚拟机内存和操作系统内存及其线程

    为什么要获取虚拟机内存和操作系统内存呢? 虚拟机内存,这里主要指JVM.为了防止有的时候因为JVM内存问题导致服务器宕机,所以有必要监控JVM的内存.当达到一定值时,通过邮件及时通知,防止线上宕机造成 ...

  2. java虚拟机内存区域的划分以及作用详解

    序言 为什么有时候学着学着会突然之间觉得一切度是那么无趣,男的每个月也有那么几天难道?哈哈,不然是什么,我还是要坚持,可以做少一点,但是不能什么度不做.总会过去的,加油 --WH 一.运行时数据区 什 ...

  3. Java虚拟机内存模型及垃圾回收监控调优

    Java虚拟机内存模型及垃圾回收监控调优 如果你想理解Java垃圾回收如果工作,那么理解JVM的内存模型就显的非常重要.今天我们就来看看JVM内存的各不同部分及如果监控和实现垃圾回收调优. JVM内存 ...

  4. Java虚拟机内存优化实践

    前面一篇文章介绍了Java虚拟机的体系结构和内存模型,既然提到内存,就不得不说到内存泄露.众所周知,Java是从C++的基础上发展而来的,而C++程序的很大的一个问题就是内存泄露难以解决,尽管Java ...

  5. 如何设置Java虚拟机内存以适应大程序的装载

    Java虚拟机对于运行时的程序所占内存是有限制的,当我们的项目或者程序很大时,往往会照成内存溢出. 举个例子: public class SmallTest1 { public static void ...

  6. 打包apk java 虚拟机内存不足

    解决方案:在android->sdk->build-tools-android-version 中有个 dx.bat dx.bat --dex 命令的dx.bat脚本有这样一句代码 REM ...

  7. Java虚拟机-内存tips

    java虚拟机内存可以分为独占区和共享区. 独占区:虚拟内存栈.本地方法栈.程序计数器. 共享区:方法区.Java堆(用来存放对象实例). 程序计数器 比较小的内存空间,当前线程所执行的字节码的行号指 ...

  8. Java虚拟机内存溢出异常--《深入理解Java虚拟机》学习笔记及个人理解(三)

    Java虚拟机内存溢出异常--<深入理解Java虚拟机>学习笔记及个人理解(三) 书上P39 1. 堆内存溢出 不断地创建对象, 而且保证创建的这些对象不会被回收即可(让GC Root可达 ...

  9. JVM基础系列第6讲:Java 虚拟机内存结构

    看到这里,我相信大家对于一个 Java 源文件是如何变成字节码文件,以及字节码文件的含义已经非常清楚了.那么接下来就是让 Java 虚拟机运行字节码文件,从而得出我们最终想要的结果了.在这个过程中,J ...

随机推荐

  1. CRNN中英文字符识别

    代码地址如下:http://www.demodashi.com/demo/13870.html 参考GitHub源码:https://github.com/YoungMiao/crnn 应demo大师 ...

  2. Ruby 和 Python 分析器是如何工作的?

    你好! 我作为一名编写Ruby profiler的先驱,我想对现有的Ruby和Python profiler如何工作进行一次调查. 这也有助于回答很多人的问题:“你怎么写一个profiler?” 在这 ...

  3. mosquitto --- 单向认证

    1.生成证书要单向配置SSL 需要 做三项前置工作 1. 生成CA证书 2.生成server 端证书,server 端key github 的一个开源项目已经做到这点 ,详情可见 https://gi ...

  4. BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第10章节--SP2013中OAuth概览 应用程序验证

    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第10章节--SP2013中OAuth概览  应用程序验证 既然你懂得了什么是应用程序身份.而且知道怎样在SP中创建和设置 ...

  5. 计算机的OSI和TCP/IP网络模型

    1.计算机的网络模型分为两种OSI模型和TCP/IP模型,它们的对应关系如下:   2.针对OSI模型,每一层都有各自的功能. 应用层 应用层是OSI模型中最靠近用户的一层,负责为用户的应用程序提供网 ...

  6. 批量修改图像的大小 Python PIL

    #-*-coding:utf-8-*- import os import os.path from PIL import Image import time def ResizeImage(filei ...

  7. AngularJS中的$apply

    $apply()方法可以在angular框架之外执行angular JS的表达式,例如:DOM事件.setTimeout.XHR或其他第三方的库. 当仅仅使用Angular所提供的对象时,你不该过多的 ...

  8. fft分析前后频谱数据

    正弦信号输入 input 输入的原始信号 short [128] fir 滤波后的输出信号 SHORT [128] fft 傅里叶变换后的freq数据  float [128] rmroise 去除底 ...

  9. 进程控制函数(2)-setpgid() 修改当前进程的进程组ID

    定义:int setpgid(pid_t pid,pid_t pgid); 表头文件:#include<unistd.h> 说明:setpgid()将参数pid 指定进程所属的组识别码设为 ...

  10. iOS-获取苹果商店iPhone应用程序编号APPID-应用中跳转到AppStore中的其他应用

    iOS-获取苹果商店iPhone应用程序编号APPID-应用中跳转到AppStore中的其他应用 一 获取苹果商店iPhone应用程序编号APPID 1 在mac上打开itunes  选择中的A 然后 ...