1.Java虚拟机运行时数据区

在前面的几篇博文中,我们只是简单的把内存区域分为了堆和栈,但其实,这种分法是十分粗糙的,jvm在实际运行的时候,内存区域的划分绝对不是那么简简单单的就两块,我们一起看下面这个图就知道了。

从上图我们知道了,JVM虚拟机运行时数据区主要划分为:方法区、虚拟机栈、本地方法栈、堆、程序计数器。

1.1程序计数器

虽然在上图中,程序计数器这块占用的区域画的很大,但其实,在内存中,它只是较小的一块内存空间。

1)生命周期:线程私有的,与它所绑定的线程相同。

2)作用:当前线程所执行的字节码的行号指示器,简单的可以理解成,程序计数器记录着下一行要执行的代码行数,比如我们经常写的分支、循环、跳转都是通过改变该计数器的值来完成的。如果一个线程正在执行的是Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器则为空。

3)程序运行时该区域可能发生的异常:此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。

1.2Java虚拟机栈

其实这里所说的栈,就是前面我们博文中粗糙分法堆栈中的栈了。精确的讲的话,其实是Java虚拟机栈中的局部变量表部分吧;同时这里是专门为虚拟机执行java方法服务的,为什么这么说呢?因为内存区域中还有本地方法栈,本地方法栈是只为虚拟机使用到的Native方法服务的。

1)生命周期:线程私有的,与它所绑定的线程相同。

2)作用:每个方法被执行的时候都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。其中局部变量表存储的是以下类型:

①基本数据类型:boolean, byte, char, short, int, float, long, double;

②对象引用:reference类型,它不等于对象本身,根据不同的虚拟机实现,它可能是一个指向对象起始地址的引用文章,也可能是指向一个对象句柄或其他与此对象有关的位置;

③returnAddress类型:指向了一条字节码指令的地址,简单的说,就是下一条要执行的代码的地址;

3)程序运行时该区域可能发生的异常:

①线程请求栈深度 > 虚拟机允许深度,抛出StackOverflowError;eg:

package edu.outofmemoryerror.heap;

public class JavaStackSOF {

private int stackLength = 1;

public void stackLeak() {

stackLength++;

stackLeak();

}

/**

* -Xss128K

* @param args

*/

public static void main(String[] args) {

JavaStackSOF sf = new JavaStackSOF();

sf.stackLeak();

}

}

运行结果是:

注意在运行的时候注意要改变那些参数;如果是通过控制台命令来执行的,可以直接跟在Java命令之后书写,如果是通过Eclipse来执行的可以在下面页面添加上再来执行,如图:

②该栈允许动态拓展,当无法申请到足够的空间时,抛出OutOfMemoryError异常;

1.3本地方法栈

本地方法栈跟虚拟机栈相似,他们的区别在前面已经提过了:本地方法栈是只为虚拟机使用到的Native方法服务的,而java虚拟机栈是专门为虚拟机执行java方法服务的。

1)生命周期:线程私有的,与它所绑定的线程相同。

2)作用:为使用到的Native方法服务。

3)程序运行时该区域可能发生的异常:跟虚拟机栈一样。

1.4Java堆(Java Heap)

对于很多应用来说,Java堆是Java虚拟机所管理的内存中最大的一块。

1)生命周期:线程共享的,在虚拟机启动时就创建

2)作用:存放对象实例,几乎所有的对象实例以及数组都在这里分配内存。

3)程序运行时该区域可能发生的异常:堆中没有内存完成实例分配或者堆无法再拓展时,将会抛出OutOfMemoryError异常,eg:

package edu.outofmemoryerror.heap;

import java.util.ArrayList;

import java.util.List;

public class HeapOOM {

static class OOMObject { }

/**

* -Xms20M -Xmx20M -XX:+HeapDumpOnOutOfMemoryError

* @param args

*/

public static void main(String[] args) {

List list = new ArrayList();

while (true) {

list.add(new OOMObject());

}

}

}

运行结果:

1.5方法区(Method Area)

方法区有一个别名叫做非堆(Non-Heap),对于习惯在HotSpot虚拟机上开发和部署程序的开发者来说,它也叫“永久代”。

1)生命周期:线程共享的,在虚拟机启动时就创建

2)作用:存储已被虚拟机加载的类信息、常量、静态变量,也就是编译器编译后的代码数据。

3)程序运行时该区域可能发生的异常:当方法区无法满足内存分配需求时,将会抛出OutOfMemoryError异常。比如java.lang.OutOfMemoryError,这个错误其实对于经常使用SSh框架进行开发的我们应该很熟悉,它就是由于方法区空间不足导致的内存溢出。

因为该区域中的垃圾收集行为是比较少出现的,所以对象相当于永久不被回收一般,所以在这个区域就叫做“永久代”了。

1.5.1运行时常量池

运行常量池是方法区的一部分。

1)生命周期:线程共享的,在虚拟机启动时就创建

2)作用:存放Class文件中类的版本、字段、方法、接口等描述信息外,还有一些信息是常量池,用于存放编译期间生产的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行是常量池中。

3)程序运行时该区域可能发生的异常:运行时是方法区的一部分,自然收到方法区内存的限制,当常量池无法在申请到内存是就会抛出OutOfMemoryError异常

看到这里,不知道大家会不会想起前面一篇博文中我们说的JVM对字符串的处理呢?

没错,在那篇博文中讲的Java字符串缓冲池,其实就是运行时常量池的一部分,而运行池是在方法区中的,方法区中的垃圾收集行为是几乎没有的,相当于不会被回收。这就是前面的JVM对字符串处理的原理了。

1.6直接内存

其实直接内存不是虚拟机运行时数据区的一部分,也不是Java虚拟机规范中的一部分,但是这部分也频繁的使用,也可能会导致OutOfMemoryError异常的出现。

2引用对象的访问

在之前我们有一篇博文讲了关于对象与内存管理的知识,但是那里只是比较简单的,下面我们更加深入了解一下,在Java语言中,对象访问是如何进行的?

其实对象访问并不像前面那篇博文中讲的那么简单只涉及到堆和栈,因为即使是最简单的访问,也会涉及到Java虚拟机栈,Java堆,方法区这三个重要的内存区域。之所以只讲堆和栈是因为开发人员在大多数情况下关注的最多的是堆和栈两个区域。

关于基本类型的访问,在前面那篇博文中我们已经讲了,下面,我们先提一下相关的概念:

1)对象类型数据:指的是该对象的对象类型,父类,实现的接口,方法等,其实就是前面说的,方法区存储的是加载的对象的信息。

2)对象实例数据:指的是该类实例化后的对象的实例变量的值。

接着,我们继续重点深入讲解下关于引用类型对象的两种访问方式:

1)使用句柄方式访问

使用这种对象的访问方式的优势是:存储的是稳定的句柄地址,在对象移动时只会改变句柄中的实例数据指针,而reference本身不用改变。

使用句柄池访问方式,Java堆中将会划分出一块内存来作文句柄池,reference中存储的是对象的句柄地址,而句柄中包含了对象实力数据和类型数据各自的具体地址信息。

其实从上图中,我们还能看出一个知识点,那就是:64位长度的long和double类型的数据会占用2个局部变量空间

2)使用直接指针访问方式

使用这种访问方式的优势是:访问速度快。

java堆栈句柄,深入了解JVM—内存区域相关推荐

  1. Java虚拟机------JVM内存区域

    JVM内存区域运行时数据区域分为两种: JVM内存区域 运行时数据区域分为两种: 线程隔离的数据区: 程序计数器 Java虚拟机栈 本地方法栈 所有线程程共享的数据区: Java堆 方法区 JVM 内 ...

  2. JVM内存区域(Java内存区域)、JVM垃圾回收机制(GC)初探

    一.JVM内存区域(Java内存区域) 首先区分一下JVM内存区域(Java内存区域)和Java内存模型(JMM)的概念.Java线程之间的通信采用的是共享内存模型,这里提到的共享内存模型指的就是Ja ...

  3. 深入理解JVM内存区域与内存分配

    前言:这是一篇关于JVM内存区域的文章,由网上一些有关这方面的文章和<深入理解Java虚拟机>整理而来,所以会有些类同的地方,也不能保证我自己写的比其他网上的和书本上的要好,也不可能会这样 ...

  4. 深入理解JVM之JVM内存区域与内存分配

    在学习jvm的内存分配的时候,看到的这篇博客,该博客对jvm的内存分配总结的很好,同时也利用jvm的内存模型解释了java程序中有关参数传递的问题. 博客出处: http://www.cnblogs. ...

  5. 深入理解Java虚拟机学习笔记-1.JVM内存模型

    JVM内存模型 1.内存模型结构图 名称 特征 作用 配置参数 异常 程序计数器 占用内存小,线程私有, 生命周期与线程相同 大致为字节码行号指示器 无 无 虚拟机栈 线程私有,生命周期与线程相同,使 ...

  6. JVM之JVM内存区域与内存分配(转载)

    2019独角兽企业重金招聘Python工程师标准>>> 先来看看JVM运行时候的内存区域 大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区),He ...

  7. JVM 内存区域大小参数设置

    需要提前了解的知识点: 1. JVM内存模型 2. JVM垃圾回收算法 下图是JVM内存区域划分的逻辑图 从图中我们大概了解JVM相关的内存区域. JVM内存包括区域 Heap(堆区) New Gen ...

  8. JVM——内存区域:运行时数据区域详解

    关注微信公众号:CodingTechWork,一起学习进步. 引言   我们经常会被问到一个问题是Java和C++有何区别?我们除了能回答一个是面向对象.一个是面向过程编程以外,我们还会从底层内存管理 ...

  9. 《探索JVM内存区域》

    一.为什么要了解JVM内存区域 二.结识JVM中的"内存"成员 1. 程序计数器(PC=Program Counter Register) 2. JVM栈(Java Virtual ...

最新文章

  1. android 广告效果图,android 仿首页广告轮播效果
  2. c语言一个整数各位数字个数_C语言实现把字符串中的数字转换成整数
  3. WinFrom下Webbrowser加载自定义页面的技巧
  4. pdf.js插件使用记录,在线打开pdf
  5. php 303,HTTP 的重定向301,302,303,307(转)
  6. 我的物联网项目(十二) 单体应用架构不行?
  7. 重温数据结构:树 及 Java 实现(转)
  8. Cloud一分钟 | 阿里云将在英国大区设立数据中心
  9. 项目管理中网络图的看法和相关参数阅读说明
  10. Linux系统编程8:入门篇之简单明了说明如何在Linux中Git提交代码
  11. hdu5354 Bipartite Graph
  12. 函数的定义与变量作用域
  13. 使用R语言中的GWmodel进行GWR模型的运算
  14. 百度网盘断点续传下载工具IDM
  15. 光影精灵usb安装linux,惠普光影精灵5笔记本怎么装win10系统(uefi+gpt)
  16. 打开JMeter报错:Could not reserve enough space for 1048576KB object heap
  17. (二)U盘安装Windows Server 2008 R2系统
  18. android广告赚钱[转]
  19. 为什么你读专业技术书逐渐焦虑,读不下去书怎么办?
  20. insert 插入数据

热门文章

  1. linux中export和source的作用和区别
  2. 众筹网02_项目环境搭建
  3. sublime编译python文件提示can't find '__main__' module in ' '
  4. [云炬创业管理笔记]第二章测试2
  5. 谈慎独2017-12-19
  6. 利用生物视觉机制提高神经网络的对抗鲁棒性 | NeurIPS 2020
  7. VisualStudioCode 中设置中文语言【图文教程】
  8. linux格式化该新添加的分区,Linux下添加新硬盘及分区格式化要点
  9. python jieba 文本相似度_文本相似度分析(基于jieba和gensim)
  10. asp.net中此页的状态信息无效,可能已损坏的解决之道