「每日五分钟,玩转JVM」:线程共享区
前言
上一篇中,我们了解了JVM中的线程独占区,这节课我们就来了解一下JVM中的线程共享区,JVM中的线程共享区是跟随JVM启动时一起创建的,包括堆(Heap)和方法区()两部分,而线程独占区的程序计数器,虚拟机栈,本地方法栈的生命周期都是跟随线程的,随线程的创建而诞生,随线程的销毁而销毁。
堆(Heap)
堆内存作为JVM管理的内存中最大的一块,用于存放我们的对象实例,我们经常会把JVM的内存简单的分为堆内存和栈内存,这样说虽然有些片面,但是也有这么说的道理,这两块儿一个作为执行程序的,一个作为存放对象的,是JVM中最为重要的两块儿内存。所以,我们的垃圾收集一般是针对的用于存放对象的堆内存,所以堆内存有时候也会被称为GC堆。
从内存分配的角度上来说,堆内存中包含了新生代内存和老年代内存,而年轻代又分为Eden和Survivor区。Survivor区由From Survivor和To Survivor组成。Eden区占大容量,Survivor两个区占小容量,默认比例是8:1:1,而且JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,所以无论什么时候,总是有一块 Survivor 区域是空闲着的。
这样设计的原因是为了更方便的进行垃圾收集,我们会在后面垃圾收集的章节中去详细的讲解。
TLAB
TLAB的全称是Thread Local Allocation Buffer,即线程本地分配缓存区,这是一个处于堆内存中线程私有的内存分配区域,默认情况下这个区域就是开启的,当然我们也可以在启动时配置XX:+UseTLAB
去开启该区域,这个区域所占空间非常的小,默认情况下只占Eden区域的1%,我们也可以通过也XX:TLABWasteTargetPercent
设置TLAB空间所占用Eden空间的百分比大小。
方法区
方法区存储虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据,在Java虚拟机的规范中,把方法区认为是堆内存的逻辑部分,但是实际上他们是完全隔离的。
在JDK 8 之前,方法区被称为(或者可以说是被实现为)持久代,永久代(Perman Gen),而在 JDK 8 之后,取消了永久代的概念,取而代之的实现是元空间(MetaSpace),原本位于永久代中的运行时常量池和静态变量都存储到了堆中,而其余的内容则是移到了元空间。
元空间的本质和永久代类似,都是对JVM规范中方法区的实现,它们之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制,但可以通过以下参数来指定元空间的大小:-XX:MetaspaceSize-XX:MaxMetaspaceSize
。
所以我们前几年JDK7盛行的时候OOM错误消息是这样的:
java.lang.OutOfMemoryError:PermGen space
而在近几年JDK8的使用中遇到的OOM是这样的:
java.lang.OutOfMemoryError:Metaspace
运行时常量池
运行时常量池位于元空间中,用于存储编译期生成的各种字面量和符号引用,而这里需要注意一点:字符串常量池从JDK 7 之后就移到了堆内存中去管理,但是运行时常量是仍然位于方法区基于JDK 8 的新实现——元空间中。
网上有部分声音说运行时常量池在JDK8移到了堆内存中,其实这种说法是错误的,真正移到堆内存的是字符串常量池,并且是在JDK7的更新中就已经移到了堆中。
更详细的关于常量池的信息我们会在类结构中去学习。
后话
每天五分钟,跟Vi玩转JVM!
下篇解密一个对象的诞生!
公众号
本文首发于公众号,扫码关注即可获取最新文章
「每日五分钟,玩转JVM」:线程共享区的更多相关文章
- 「每日五分钟,玩转 JVM」:GC 概览
前言 GC(Garbage Collection)是我们在学习 JVM 的过程中不可避免的一道坎,接下来,我们就来系统的学习一下 GC. 做一件事情之前,我们一定要去知道我们为什么要去做,这里不仅仅指 ...
- 「每日五分钟,玩转JVM」:线程独占区
前言 如果我们对计算机组成有所了解,那么我们一定会知道在计算机中有一块儿特殊的区域,称之为寄存器,寄存器包括了指令寄存器和程序计数器,这两样位于CPU中,作为程序运行的大脑来控制程序的运行和流转. 而 ...
- 「每日五分钟,玩转JVM」:对象从哪来
面向对象 众所周知,Java是一门面向对象的高级编程语言,那么现在问题来了,对象从哪来呢?有些人会说通过new关键字来创建一个对象,说的很好,本篇我们就来解密在new一个对象的过程中,JVM都给我们做 ...
- 「每日五分钟,玩转JVM」:对象内存布局
概览 一个对象根据不同情况可以被划分成两种情况,当对象是一个非数组对象的时候,对象头,实例数据,对齐填充在内存中三分天下,而数组对象中在对象头中多了一个用于描述数组对象长度的部分 对象头 对象头分为两 ...
- 「每日五分钟,玩转JVM」:指针压缩
64位JVM和32位JVM 最初的时候,JVM是32位的,但是随着64位系统的兴起,JVM也迎来了从32位到64位的转换,32位的JVM对比64位的内存容量比较有限,但是我们使用64位虚拟机的同时,也 ...
- 「每日五分钟,玩转JVM」:两种算法
前言 上篇文章,我们了解了GC 的相关概念,这篇文章我们通过两个算法来了解如何去确定堆中的对象实例哪些是我们需要去回收的垃圾对象. 引用计数算法 引用计数法的原理很简单,就是在对象中维护一个计数器,当 ...
- zookeeper-架构设计与角色分工-《每日五分钟搞定大数据》
本篇文章阅读时间5分钟左右 点击看<每日五分钟搞定大数据>完整思维导图 zookeeper作为一个分布式协调系统,很多组件都会依赖它,那么此时它的可用性就非常重要了,那么保证可用性的同 ...
- zookeeper核心-zab协议-《每日五分钟搞定大数据》
上篇文章<paxos与一致性>说到zab是在paxos的基础上做了重要的改造,解决了一系列的问题,这一篇我们就来说下这个zab. zab协议的全称是ZooKeeper Atomic Bro ...
- HDFS-异常大全-《每日五分钟搞定大数据》
点击看<每日五分钟搞定大数据>完整思维导图以及所有文章目录 问题1:Decomminssioning退役datanode(即删除节点) 1.配置exclude: <name>d ...
随机推荐
- 使用 Spring Framework 时常犯的十大错误
Spring 可以说是最流行的 Java 框架之一,也是一只需要驯服的强大野兽.虽然它的基本概念相当容易掌握,但成为一名强大的 Spring 开发者仍需要很多时间和努力. 在本文中,我们将介绍 Spr ...
- Servlet和JSP知识总结
1.Servlet接口有哪些方法及Servlet生命周期 Servlet接口定义了5个方法,前三个方法与Servlet生命周期有关: void init() void service() void d ...
- File文件类
目录 File文件类 File类的构造方法 File类的创建功能 File类的重命名 File类的删除功能 File类的判断功能 File类的获取功能 文件名称过滤器 File文件类 File:文件和 ...
- codemirror使用
JS使用 使用bower下载 bower i codemirror 引入样式文件 <link rel="stylesheet" type="text/css&quo ...
- swift对象存储
swift对象存储 简介 OpenStack Object Storage(Swift)是OpenStack开源云计算项目的子项目之一,被称为对象存储,提供了强大的扩展性.冗余和持久性.对象存储,用于 ...
- Kotlin学习快速入门(2)——条件 数组 循环 方法
条件 if条件判断 常用的判断和Java一样,这里提一下不同的用法 1.if可以作为三元运算符 val max = if (a > b) a else b 2.使用in判断是否在某个区间 val ...
- TCP三次握手和断开四次挥手
TCP三次握手 1主机A发送消息请求与主机B连接 2主机B回复消息同意与主机A连接 3主机A确认主机B的同意连接,并建立连接 TCP的四次挥手 1客户端发送FIN到服务器,请求关闭与服务器的连接(意思 ...
- 灵活使用Maven Profile
项目中一直应用Maven的profile特性解决不同环境的部署问题.最近在尝试解决本地调试环境的时候碰到一些问题,顺便仔细研究了一下.因为项目仍然在用普通SpringMVC架构,没有切换到Spring ...
- 【iOS】沙盒目录
有关沙盒目录参考: http://blog.csdn.net/totogo2010/article/details/7669837 获取沙盒路径,参考代码: NSArray *paths = NSSe ...
- linux字符设备驱动中内核如何调用驱动入口函数 一点记录
/* 内核如何调用驱动入口函数 ? *//* 答: 使用module_init()函数,module_init()函数定义一个结构体,这个结构体里面有一个函数指针,指向first_drv_init() ...