《深入理解 Java 虚拟机》学习笔记 -- 内存区域

运行时数据区域

主要分为 6 部分:

  1. 程序计数器
  2. 虚拟机栈
  3. 本地方法栈
  4. Java 堆
  5. 方法区

如图所示:

1. 程序计数器(线程私有)
  1. 程序计数器是当前线程所执行字节码的行号指示器
  2. 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令
  3. 为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器
  4. 执行 Java 方法,计数器记录的是正在执行的虚拟机字节码指令的地址;执行的是 Native 方法,计数器为空
  5. 程序计数器是唯一一个在 Java 虚拟机中不会出现 OutOfMemoryError 情况的区域
2. Java 虚拟机栈(线程私有)
  1. 每个方法被执行的时候都会同时创建一个栈帧
  2. 每一个方法被调用直至执行完成的过程,就对应者一个栈帧再虚拟机中从入栈到出战的过程
  3. ”栈内存“指的就是虚拟机栈中的局部变量表部分
  4. 局部变量表存放的是基本数据类型
  5. 局部变量表所需的内存空间再编译期间完成分配
  6. StackOverflowError : 线程请求的栈深度大于虚拟机所允许的深度
  7. OutOfMemoryError: 虚拟机栈动态扩展无法申请到足够的内存
3. 本地方法栈(线程私有)
  1. 运行本地方法
  2. 其他和 Java 虚拟机栈类似
4. Java 堆(线程共享)
  1. 在虚拟机启动时创建
  2. 存放对象实例
  3. 垃圾回收主要区域
5. 方法区(线程共享)
  1. 存储已被虚拟机加载的类信息,常量,静态变量,即编译器编译后的代码等数据
  2. 对常量池的回收和对类型的卸载

其他

运行时常量池
  1. 运行时常量池是方法区的一部分,
  2. 类加载后将 Class 文件中的常量池信息放到方法区的运行时常量池中
  3. String 类的 intern() 方法可以把运行期间新的常量放入池中
直接内存
  1. 直接内存并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域

举例

请看下面例子:

public class Test {

    public static void main(String args[]) {

    	String s1 = "abc";
String s2 = "abc"; System.out.println(s1 == s2); String s3 = new String("abc"); System.out.println(s1 == s3); System.out.println(s1 == s3.intern()); } }

打印结果为:

true
false
true

解析:

  1. 第一个 true 是因为 "abc" 为字符串常量,是放在方法区中的,虽然会开启内存但是会统一指向到运行时常量池中的 HashSet,由 HashSet 统一管理,这时 s1, s2 指向的地址自然就是 HashSet,s1 == s2 当然为 true
  2. 第二个为 false 是因为 s3 是一个对象实例,实例是放在 Java 堆中,s1 是放在方法区中,两者地址不一样,所以为 false
  3. 第三个为 true 是因为 intern() 方法可以把新的常量放入池中,所以为 true

《深入理解 Java 虚拟机》学习笔记 -- 内存区域的更多相关文章

  1. 深入理解Java虚拟机学习笔记(一)-----Java内存区域

    一 概述 对于 Java 程序员来说,在虚拟机自动内存管理机制下,不再需要像C/C++程序开发程序员这样为内一个 new 操作去写对应的 delete/free 操作,不容易出现内存泄漏和内存溢出问题 ...

  2. 深入理解java虚拟机学习笔记(一)JVM内存模型

    上周末搬家后,家里的宽带一直没弄好,跟电信客服反映了N遍了终于约了个师傅明天早上来迁移宽带,可以结束一个多星期没网的痛苦日子了.这段时间也是各种忙,都一个星期没更新博客了,再不写之前那种状态和激情都要 ...

  3. 深入理解java虚拟机学习笔记(二)垃圾回收策略

    上篇文章介绍了JVM内存模型的相关知识,其实还有些内容可以更深入的介绍下,比如运行时常量池的动态插入,直接内存等,后期抽空再完善下上篇博客,今天来介绍下JVM中的一些垃圾回收策略.        一. ...

  4. 深入理解Java虚拟机学习笔记(二)-----垃圾收集器与内存分配策略

    写在前面 本节常见面试题: 如何判断对象是否死亡(两种方法). 简单的介绍一下强引用.软引用.弱引用.虚引用(虚引用与软引用和弱引用的区别.使用软引用能带来的好处). 如何判断一个常量是废弃常量 如何 ...

  5. 深入理解Java虚拟机 - 学习笔记 1

    Java内存区域 程序计数器 (Program Counter Register) 是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器.在虚拟机的概念模型里,字节码解释器工作时就是通过 ...

  6. 深入理解java虚拟机学习笔记(二)

    第三章 垃圾收集器与内存分配策略 概述 ​ 程序计数器.虚拟机栈.本地方法栈3个区随线程而生,随线程而灭.因此大体上可认为这几个区域的内存分配和回收都具备确定性.在方法/线程结束时,内存自然就跟着回收 ...

  7. 深入理解java虚拟机学习笔记(一)

    第二章 Java内存区域与内存溢出异常 运行时数据区域 程序计数器(Program Counter Register) 程序计数器:当前线程所执行的字节码行号指示器.各条线程之间计数器互不影响,独立存 ...

  8. 深入理解Java虚拟机学习笔记(三)-----类文件结构/虚拟机类加载机制

    第6章 类文件结构 1. 无关性 各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节码(即扩展名为 .class 的文件) 是构成平台无关性的基石. 字节码(即扩展名为 .class 的文 ...

  9. 类加载机制(深入理解JAVA虚拟机学习笔记)

    1.类加载机制的定义 将class文件加载到内存,然后对class文件中的数据进行校验.解析和初始化,转换成可以被虚拟机直接使用的JAVA类型,这就是虚拟机的类加载机制.(在JAVA中,类的加载.连接 ...

随机推荐

  1. springboot 配置跨越访问

    import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.http.H ...

  2. Mysql索引查询失效的情况

    首先,复习一下索引的创建: 普通的索引的创建: CREATE INDEX  (自定义)索引名  ON  数据表(字段); 复合索引的创建: CREATE INDEX  (自定义)索引名  ON  数据 ...

  3. ES节点分析

    ES集群概念 集群 一个集群cluster由一个或者多个节点组成,具有相同的cluster.name,协同工作,分项数据和负载. 当有新的节点加入或者删除了一个节点时,集群回感知到并能够平衡数据. E ...

  4. Kafka Eagle 安装

    Kafka Eagle 是一款开源的 Kafka 集群监控系统. 一.下载 https://download.kafka-eagle.org/ 二.安装 # 解压 .tar.gz -C /opt/ / ...

  5. qcow2镜像制作

    windows 1.准备windows镜像.驱动镜像. 驱动下载地址: https://docs.fedoraproject.org/en-US/quick-docs/creating-windows ...

  6. Docker-----关于dockerfile

    docker build参数说明 --no-cache :创建镜像的过程不使用缓存: --force-rm :设置镜像过程中删除中间容器: --network=host:容器会使用宿主机的网络,容器与 ...

  7. Expecting "jsp:param" standard action with "name" and "value" attributes

    浏览器访问报如下jsp标签错误: 根据提示,定位到jsp页面124行,代码如下: 查找原因,当<jsp:include></jsp:include>标签中没有参数时,不允许有空 ...

  8. sql拼接中的小错误

    字符串类型变量拼接到sql字符串上,容易忘记添加单引号,使用jdbcTemplate执行,报如下错误 正确写法如下:

  9. 连载一:RobotFramework+SeleniumWebdriver+RIDE的安装

    安装前说明: Robot Framework自动化测试框架+可视化编辑工具RIDE+Selenium2这是规范的webAPI. 一.通过下载安装包安装 1)RF 框架是基于 Python 语言的,所以 ...

  10. linux无密钥登陆

    1.在用户目录下执行命令 ssh-keygen -t rsa 一路回车: 2.在当前用户目录下,进入.ssh文件夹(.ssh文件夹为隐藏文件夹,直接进去即可). 在.ssh文件夹下执行命令: cat ...