前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(2)JVM——Java 虚拟机运行时数据区域讲解

(2)JVM——Java 虚拟机运行时数据区域讲解

作者头像
凡人飞
发布2020-09-20 20:17:26
3990
发布2020-09-20 20:17:26
举报
文章被收录于专栏:指缝阳光指缝阳光

一、简述

  1. 介绍:如果有了解 C/C++,以及 Java 语言的朋友,肯定知道它们之间最大的差别的就是对于内存的回收。用 C/C++ 时,自己创建的对象得自己回收内存,而 Java 则是因为其自带的垃圾收集器,将开发者解放出来。犹记得当初大学学 C 语言,讲到指针的那一节,就感觉指针是无所不能,各种灵活,不过如果用不好就容易飘。本篇博客主要简单介绍一下 Java 虚拟对于内存的划分,以及大概作用。

二、内存运行时数据区

Java虚拟机运行时数据区
Java虚拟机运行时数据区
  1. 这张图片展示的就是 JVM 对于内存的经典划分,主要分为了程序计数器虚拟机栈本地方法栈方法区,同时还有运行时常量池直接内存
  2. 程序计数器
    • 线程私有(每条线程独立有一个),可以看成当前线程所执行的字节码的行号指示器。
    • 如果线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是本地方法,这个计数器值则应为空。
    • 此内存区域是唯一没有 OutOfMemoryError 情况的区域
  3. 虚拟机栈: 通俗的讲,一个线程有一个虚拟机栈,这个栈就是一个中间容器,帮助线程在执行过程中完成各项处理。其中栈里面的一个基础单位就是栈帧,一个栈帧可以简单的对应一个方法,在进入方法后会有局部变量等数据,此时就创建一个栈帧来保存这些信息(比如局部变量表、操作数栈、动态连接、方法出口等信息)。栈是先进后出的数据结构。虚拟机栈特点如下:
    • 线程私有,生命周期与线程相同
    • 一个方法的执行对应一个栈帧的入栈和出栈过程
    • 局部变量表存放 8 种基本数据类型、对象引用和 returnAddress 类型
    • long 和 double 占用两个变量槽,其他类型是只占一个
    • 两类异常状况: ① 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出 StackOverFlowError 异常 ② 如果 Java 虚拟机栈容量可以动态扩展(HotSpot 不可以),当栈扩展时无法申请到足够的内存会抛出 OutOfMemoryError 异常
  4. 本地方法栈:本地方法栈和虚拟机栈基本一样,区别是 虚拟机栈为虚拟机执行 Java 方法(字节码)服务,而本地方法栈是为虚拟机使用到的本地方法服务 。异常和虚拟机栈的一致。本地方法解释可以查看——详解native方法的使用
  5. Java 堆:堆是虚拟机管理的内存中最大的一块,这块地方存放了 Java 中几乎所有的对象实例(有容乃大)。因为这块地方大,并且发生的故事多,所以内存的回收(垃圾收集器)都发生在这儿,因此也被叫为 “GC堆”。有四处特点如下:
    • 虽然堆是线程共享的,但是在共享的地方也会为线程划分私有的分配缓冲区
    • Java 堆在内存物理上可能不连续,但是对于我们使用来说,逻辑上是连续的
    • 虚拟机实现堆是可扩展的,通过参数 -Xmx 和 -Xms 设置
    • 在堆中没有内存可以进行实例分配时,也无法扩展,则会抛出 OutOfMemoryError 异常
  6. 方法区:与 Java堆 一样是线程共享的,用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。注意:经常会将“永久代”和方法区混淆,他们的区别是 方法区是 JVM 的一种规范,而永久代是对这一种规范的实现。查看:方法区和永久代区别。特点如下:
    • 在 jdk7 中已经将字符串常量池从方法区移除,并在Java堆中开辟一块新的区域存放字符串常量池
    • 在 jdk8 中将永久代去除了,使用元空间来实现,元空间的内存区域使用本地内存
    • 如果方法区无法满足新的内存分配需求时,将抛出 OutOfMemoryError 异常
  7. 运行时常量池:运行时常量池是方法区的一部分,存放编译器生成的各种字面量和符号引用。特点如下:
    • 具备动态性,常量池的数据不是都在编译器存入的,还可以在运行时添加,比如 String 的 intern() 方法
    • 常量池无法申请到内存时抛出 OutOfMemoryError 异常
    • 对于各个版本方法区的区别如表格 1-1
  8. 直接内存:直接内存不是虚拟机运行时数据的一部分,其分配不会受到 Java 堆大小的限制。
    • 在 JDK1.4 中新加入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,在一些场景能显著提高性能
    • 也可能出现 OutOfMemoryError 异常

表格 1-1

jdk1.7以前

jdk1.7

jdk1.8

字符串常量池在方法区中,实现为永久代

字符串常量池在堆中,实现为永久代

字符串常量池在堆中,实现为元空间

深入理解Java虚拟机第三版》

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-08-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、简述
  • 二、内存运行时数据区
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档