jvm(2)-java内存区域

【0】README
0.1)本文转自 深入理解jvm, 旨在学习 java内存区域 的基础知识;

【1】运行时数据区域
1)jvm 所管理的内存将会包括以下几个运行时数据区域
1.1)
方法区;(线程共享)
1.2)虚拟机栈;(线程私有)
1.3)本地方法栈;(线程私有)
1.4)java 堆;(线程共享)
1.5)程序计数器;(线程私有)
Attention) 除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生 OutOfMemoryError(内存溢出) 异常的可能;

【1.1】程序计数器(线程私有)
1)程序计数器:
是一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器;(干货——程序计数器==行号指示器)
2)其作用:
为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,我们称这类内存区域为“线程私有”的内存;
3)此内存区域:是唯一一个在 jvm 规范中 没有规定任何 OutOfMemoryError 情况的区域;

【1.2】java 虚拟机栈(线程私有,用于存储局部变量表,操作数栈,动态链接,方法出口等信息)
1)虚拟机栈的作用:
描述的是 java 方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息;
2)局部变量表: 存放了编译器可知的基本数据类型,对象引用 和 return address 类型(指向了一跳字节码指令的地址);
3)局部变量空间(Slot): 其中64 位长度的long 和 double 类型数据都会占用两个局部变量空间(slot),其余的数据类型占用1个;(干货——引入slot==局部变量空间)
4)jvm 在该区域规定了两种异常: 
Exception1)
如果线程请求的栈深度大于jvm 所允许的深度,将抛出 StackOverFlowError 异常;
Exception2)如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出 OutOfMemoryError 异常;

【1.3】本地方法栈(线程私有)
1)
本地方法栈的作用于 虚拟机栈的作用相似;
2)他们作用的区别在于: 虚拟机栈为虚拟机执行 java(字节码)服务,而本地方法栈为 虚拟机使用到的 Native 方法(本地方法)服务;

【1.4】java 堆(存放对象实例,线程共有)
1)java 堆的唯一作用:
存放对象实例,几乎所有的对象实例都在这里分配内存;
2)GC堆(垃圾收集堆): java 堆是垃圾收集器管理的主要区域,因此很多时候也被称为 GC堆(Garbage Collected Heap);
3)从内存回收的角度看:由于现在收集器基本都采用分代收集算法,所以 java 堆还可以分为: 新生代 和 老年代;(干货——在java堆中引入新生代和老年代)
4)从内存分配的角度来看:
线程共享的 java 堆可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB);
5)java堆 可以处理物理上不连续的内存空间中, 只要逻辑上是连续的即可;
6) java 堆是可扩展的,不过当前主流的jvm 都是按照可扩展来实现的(通过 Xmx 和 -Xms 控制), 如果在堆中没有内存完成实例分配,并且堆也无法再扩展,将会抛出 OutOfMemoryError 异常;

【1.5】方法区(用于存放 class 的相关信息,线程共有)
1)方法区的作用:
用于存储被虚拟机加载的类信息,常量,静态变量,即时编译器(JIT)编译后的代码等数据;
2)方法区除了和 java 堆一样不需要连续的内存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集;
3) 方法区的内存回收目标: 主要是针对常量池的回收和对类型的卸载;

【1.6】运行时常量池
1)
运行时常量池是方法区的一部分;
2)Class 文件中除了有类的版本,字段,方法,接口等描述信息外,还有一个信息——常量池;(干货——引入常量池)
3)常量池的作用:
用于存放编译器生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放;
4)运行时常量池的一个重要特征:具备动态性;(干货——运行时常量池的具备动态性)
看个荔枝):
并非预置入 Class 文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中, 这种特性被开发人员利用的多的便是 String类的 intern 方法;

【1.7】直接内存
0)直接内存:
分配在本机直接内存上,不是 jvm 运行时数据区的一部分,但被频繁地使用;
1)jdk1.4 中新加入了NIO(new input/output)类: 引入了一种基于通道与缓冲区(buffer)的IO方式,他可以使用 Native 函数库直接分配堆外内存,然后通过一个存储在java 堆中的DirectByteBuffer 对象作为这块内存的引用进行操作,这样能在一些场景中提高性能,因为避免了在 java 堆 和 Native 堆中来回复制数据;
2)显然,本机直接内存的分配不会受到 java 堆大小的限制;

【2】HotSpot 虚拟机对象探秘
1)对象的创建steps:
step1)是否执行类加载过程:
虚拟机遇到一条new指令,首先去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载,解析和初始化过。如果没有,那必须执行相应的类加载过程;
step2)分配内存: 接下来 虚拟机将为新生对象分配内存。(内存分配方式有: 指针碰撞 和 空闲列表)
problem):对象创建在虚拟机中是非常频繁的行为,即使是仅仅修改一个指针指向的位置, 在并发情况下也并不是线程安全的。如,可能出现正在给对象A分配内存,指针还未来得及修改,对象B 又同时使用了原来指针来分配内存的情况;
solution1):对分配内存空间的动作进行同步处理——实际上采用 CAS 配上失败重试的方式保证更新操作的原子性;
solution2):吧内存分配的动作按照线程划分在不同的空间中进行,即每个线程在 java堆中预先分配一小块内存,称为本地线程分配缓冲(Thread Local Allocation Buffer,TLAB),只有TLAB用完并分配新的TLAB时,才需要同步锁定;(干货——每个线程在 java堆中预先分配一小块内存,称为本地线程分配缓冲)
step3)初始化为零:
内存分配完成后,虚拟机需要将分配到 的内存空间都初始化为零值;
step4)虚拟机对对象进行必要的设置: 如这个对象的类是什么,如果才能找到类的元数据信息,对象的哈希码,对象的GC 分代年龄等信息。这些信息存放在对象的对象头中;(干货——引入了对象头)
step5)执行 <init>方法:
执行完new 执行后,会执行 init 方法,把对象按照程序员的意愿进行初始化;

【2.1】对象的内存布局
1)对象的内存布局分为3个区域:
对象头, 实例数据 和 对齐填充;
2)HotSpot 虚拟机的对象头包括两部分数据:
2.1)对象头第一部分(Mark Word):
用于存储对象自身的运行时数据,如哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳,这部分数据的长度在 32位 和 64 位的虚拟机(未开启压缩指针)中分别为 32bit 和 64 bit, 官方称为 “Mark Word”;(干货——引入对象头的Mark Word);对象头信息是与对象自身定义 的数据无关的额外存储成本,考虑到虚拟机的空间效率,Mark Word被设计成 非固定的数据结构以便在 极小的空间内存储尽量多的信息;(干货——对象头信息是与对象自身定义 的数据无关的额外存储成本)
Complementary)
HotSpot 虚拟机对象头 Mark Word:
2.2)对象头第二部分(类型指针):类型指针, 即对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例;
3)对象的实例数据区域:是对象真正存储的有效信息,也是在程序代码中所定义的各种类型的字段内容;
4)对象的对齐填充区域: 没有什么特别的含义,它仅仅起着占位符的作用, 换句话说,就是对象的大小必须是 8字节 的整数倍;

【2.3】对象的访问定位
1)
java 程序需要通过 栈上的 引用数据来操作堆上的具体对象。
2)引用应该通过何种方式去定位,访问堆中的对象的具体位置,目前主流的访问方式有 使用句柄 和 直接指针两种;(干货——栈上引用访问堆上对象的主流访问方式)
2.1)使用句柄访问方式:
那么java 堆中将会划分出一块内存来作为句柄池,引用数据中存储的就是对象的句柄地址,而句柄地址包含了对象实例数据和类型数据各自的具体地址;

2.2)使用直接指针访问(Sun HotSpot 使用这种方式访问)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331365.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Socket编程总结

一、网络API InetAddress     用于标识网络上的硬件资源&#xff0c;主要是IP地址 URL         统一资源定位符&#xff0c;通过URL可以直接读取或写入网络上的数据Sockets      使用TCP协议实现的网络通信Socket相关的类Datagram     使用UDP协议&am…

java插入排序_Java程序要插入排序

java插入排序Java程序插入示例的排序。 显示了示例仿真以及时间复杂度。 插入排序是一种简单的排序算法&#xff0c;可以一次构建一个最终的排序数组&#xff08;或列表&#xff09;。 它比冒泡排序有效得多&#xff0c;并且在大型列表上的效率比快速排序 &#xff0c;堆排序或…

jvm(2)-JVM内存的设置(解决eclipse下out of memory问题)

【0】README 0.1&#xff09;本文转自&#xff1a; http://blog.csdn.net/sjf0115/article/details/8889201 一、JVM内存的设置的原理 默认的java虚拟机的大小比较小&#xff0c;在对大数据进行处理时java就会报错&#xff1a;java.lang.OutOfMemoryError。 设置jvm内存的方…

Java Servlet总结

一、Servlet简介 Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称&#xff0c;称为小服务程序或服务连接器&#xff0c;用Java编写的服务器端程序&#xff0c;主要功能在于交互式地浏览和修改数据&#xff0c;生成动态Web内容。狭义的Servlet是指Java语言实…

java oca_OCA第1部分中的Java难题

java oca我在业余时间正在阅读Mala Gupta的Oracle认证Java SE程序员助理书&#xff0c;我对所学到的一些新知识感到惊讶。 有时候他们真的没有道理&#xff0c;有时候他们说得通&#xff0c;但真的让人惊讶。 因此&#xff0c;在本系列文章中&#xff0c;我想将它们共享为“ Ja…

jvm(1)-走进java

【0】README0.1&#xff09;本文转自 深入理解 jvm&#xff0c;旨在了解 java 体系结构&#xff1b;【1】java技术体系1&#xff09; Sun 官方所定义的java 技术系统包括以下几个组成部分&#xff1a; java 程序设计语言&#xff1b;各种硬件平台上的java 虚拟机&#xff1b;Cl…

Java 高并发下的实践

一、使用的技术HashMap ConcurrentHashMap Lock ReadWriteLock synchronized 二、一百万并发下的组合 ConcurrentLockMap /** To change this license header, choose License Headers in Project Properties.* To change this template file, choose Tools | Templates* …

java oca_OCA第2部分中的Java难题

java oca欢迎使用OCA的Java Puzzlers的第二部分。 在这一部分中&#xff0c;我们将看到一个有趣的案例&#xff0c;涉及Java 7附带的数字文字中的下划线分隔符。 在下面的类中&#xff0c;您可以在十进制文字中看到分隔符下划线。 还请注意&#xff0c;该类现在可以正常编译。…

jvm(2)-OutOfMemoryError 异常(内存溢出异常)

【0】README0.1&#xff09;本文转自 深入理解 jvm&#xff0c; 旨在学习 OutOfMemoryError 异常&#xff08;内存溢出异常&#xff09; 的触发类型&#xff1b;0&#xff09;准备知识0.1&#xff09;除了程序计数器外&#xff0c;虚拟机内存的其他几个运行时区域&#xff08;方…

java oca_OCA第7部分中的Java难题

java oca在OCA系列的Java Puzzlers的这一部分中&#xff0c;我将展示定义字符串和与之相关的潜在惊喜的多种方法。 创建字符串的两种基本类型是使用new关键字和仅使用字符串文字来创建。 String strWithNew new String( "hey" ); String strWithLiteral "ho&…

Java GC总结

一、gc两大基本算法1、引用计数法 2、根搜索法 二、gc改进收集算法 1、标记-清除算法 2、复制算法 3、标记-整理算法 分代收集算法 三、gc的类型 串行垃圾回收器&#xff08;Serial Garbage Collector&#xff09; 并行垃圾回收器&#xff08;Parallel Garbage Collecto…

让CentOS能用yum自动安装rar和unrar

【0】README 0.1&#xff09;本文转自&#xff1a; http://www.centoscn.com/CentOS/config/2015/0520/5485.html 目的&#xff1a;让CentOS能用yum自动安装rar和unrar 系统环境&#xff1a; CentOS 7.0 具体操作步骤如下&#xff1a; 1.编辑文件 编辑dag.repo文件&#xff0c…

java oca_OCA第6部分中的Java难题

java oca即使对于新的Java开发人员&#xff0c;构造函数也可能不是什么大谜。 本质上&#xff0c;当您创建一个类的实例时&#xff0c;该类的构造函数就会启动。 在Java Puzzlers系列的第6部分中&#xff0c;我们将看到一个与构造函数有关的案例。 public class Puzzler { publ…

Java 内存泄露总结

一、Java内存泄漏引起的原因&#xff1a;内存泄漏是指无用对象&#xff08;不再使用的对象&#xff09;持续占有内存或无用对象的内存得不到及时释放&#xff0c;从而造成内存空间的浪费称为内存泄漏。 二、内存泄露的方式 1、静态集合类引起内存泄漏 像HashMap、Vector等的使…

使用Mockito的Mock Void方法

大家好&#xff01; 在我们之前的博客关于thenReturn和thenAnswer模拟方法之间的区别之后 &#xff0c;我们又回来了关于Mockito的另一个有趣的博客。 在这里&#xff0c;我们将讨论“如何用Mockito模拟无效方法”。 让我们开始吧&#xff01; 在编写代码时&#xff0c;总是至…

System.gc()调用 - 适用的场景

一、System.gc()调用 System.gc()用于调用垃圾收集器&#xff0c;在调用时&#xff0c;垃圾收集器将运行以回收未使用的内存空间。它将尝试释放被丢弃对象占用的内存。然而System.gc&#xff08;&#xff09;调用附带一个免责声明&#xff0c;无法保证对垃圾收集器的调用。我们…

将模板方法模式应用到kmeans聚类算法

【0】README 0.1&#xff09;本文描述和源代码均为原创&#xff0c;旨在说明 如何将模板方法模式应用到kmean聚类算法&#xff1b; 0.2&#xff09;模板方法模式的intro&#xff0c; 参见 模板方法模式 0.3&#xff09;for kmeans alg source code, please visit kmeans&a…

java oca_OCA第4部分中的Java难题

java oca在Java Puzzlers的第四部分中&#xff0c;我们有一些与char类型有关的东西。 public class Puzzler { public static void main(String[] args){ char myChar a ; myChar; System.out.println(myChar); } } 您可能已经猜到了。 它将打印“ b”&#xff0c;其原因是c…

毕业设计的十大问题

一、vue的跨域问题 1、前端本地用代理软件代理服务器 在vue项目下的 config/index.js 文件里面配置代理proxyTable:proxyTable: {/login: {target: http://192.168.1.1:8080/ntd/data,changeOrigin: true,pathRewrite: {^/login:}}2、后台服务器开启允许跨域的响应头 直接在tom…

设计模式入门(策略模式)

【0】README0.1&#xff09;本文部分文字描述转自 “head first 设计模式”&#xff0c;旨在学习 设计模式入门&#xff08;策略模式&#xff09; 的基础知识&#xff1b;0.2&#xff09;本文章节4和5的source code&#xff0c;参见 设计模式——策略模式源代码【1】看个荔枝&a…