热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

javasparksession运行时属性_Java运行时数据区域介绍

前言相信学习过CC的朋友们肯定对指针这个概念印象深刻,有了指针,我们就可以随意操作分配给程序的这一块内存,此时此刻内存就是恕瑞玛ÿ
8fb7d8401430bcb63414895f8ce2fcd4.png

前言

相信学习过C/C++的朋友们肯定对指针这个概念印象深刻,有了指针,我们就可以随意操作分配给程序的这一块内存,此时此刻内存就是恕瑞玛,程序员就是黄鸡,可以主宰内存里的一切。

但与此同时,权力的代价就是我们需要花费更多的精力在内存管理上,规定某些变量何时生何时死。很明显,这大大增加了一个大型的C/C++系统中程序员的工作量。

在Java中,指针这个概念被删除了,和它有着类似作用的是一个叫做引用的东西,同时引入了Java虚拟机(Java Virtual Machine),这可是个好东西,有了JVM后,程序员不用在内存管理上再亲历亲为了,内存泄露和溢出的问题也减少了很多(计算机永远不会错!)

但是问题的减少不代表问题就此消失,如果不了解JVM的话可能无法很好的排查错误,所以用这一篇文章来介绍一下JVM内存中的各个区域

bc6d0dc83097b4ef539c67fabaa0b896.png

下面会一个个介绍这些区域的作用

程序计数器 PCR

程序计数器其实就是字节码解释器工作时使用的一个标志,它标志了当前进行到哪个行号了,是程序控制流的指示器。在Java多线程开发的时候,每个线程都分配了一块内存,不同线程之间来回切换,为了从A线程切换到B线程再切换回A线程时可以定位到之前执行的位置,每个线程都被分配了一个PCR。这个内存区域不会有任何OutOfMemoryError的情况。

如果线程执行一个Java方法,那么PCR记录的时虚拟机字节码的地址,如果是本地方法,那么计数器的值为Undefined

Java 虚拟机栈 VM Stack

Java虚拟机栈也是线程私有的,它描述的是Java方法执行的线程内存模型,在我们使用.run方法的时候,不同线程之间都有自己的一个栈帧用来存储局部变量表,操作数栈,动态连接,方法出口等,这块学过计算机系统的朋友应该都很熟悉了。

VM Stack中存放了编译期可知的各种基本数据类型,对象引用和returnAddress,这些数据类型在局部变量表以局部变量槽表示。局部变量表所需要的内存空间在编译期完全确定,也就是说,进入一个方法后,这个方法需要在它的栈帧中分配多大的局部变量表是完全确定的。这里的“大小”值的是变量槽的数量,虚拟机最后使用了多大的空间因不同版本的虚拟机而异。

这个内存区域会发生两类异常,一个是线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError,如果Java虚拟机栈容量允许动态扩展,当拓展到极限的时候会抛出OutOfMemoryError

本地方法栈

本地方法栈和VM Stack的作用基本相同,区别在于VM Stack是为Java方法服务,本地方法栈为本地方法服务,也会有上述的两种异常。

Java 堆

Java堆是虚拟机所管理的内存中最大的一块,被所有线程共享,这个区域存在的唯一目的就是存访对象的实例,Java程序中几乎所有的对象实例都在堆上分配内存。不过由于技术(即时编译,逃逸分析,标量替换)的进步,可能以后并不是所有的Java对象实例都会在堆上被分配。

同时,Java堆还是GC(Garbage Collected)管理的内存区域,由于现代垃圾收集器大部分都是基于分代收集理论设计的,所以java堆中经常出现“新生代”,“老年代”等名词。

从分配内存的角度看,所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer)来提升对象分配时的效率。

TLAB的能够让每个Java线程能使用自己专属的分配指针来分配空间,均摊对Java堆里共享的分配指针做更新而带来的同步开销,这个内容会用一篇新的文章来讲,这里就不继续展开了。

但是无论如何划分,Java堆中存储内容的共性不会被改变,无论哪个区域,存储的都是对象实例,划分是为了更快的分配内存和更好的回收。

Java堆可以处于物理上不连续的内存空间中,但是逻辑上它是连续的,就像磁盘一样,但是对于体积较大的对象,从效率和简单的角度出发,虚拟机会将它们放在连续的空间中,这里涉及到Cache的内容,计算机专业的朋友对这个应该比较熟悉。

在主流的JVM中,Java堆的大小是可拓展的,可以通过参数-Xmx和-Xms设置,当堆无法再扩展且还有对象实例需要分配的时候,JVM会抛出OutOfMemoryError异常。

方法区

方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

对于HotSpot虚拟机来说,在JDK 6之前,运行时常量池是方法区的一部分,同时方法区里面存储了类的元数据(变量名,方法名,访问权限等),即时编译器编译后的代码(比如spring 使用IOC或者AOP创建bean时,或者使用cglib,反射的形式动态生成class信息等)等。

JDK 7之后,运行时常量池就被移出去了。到了JDK 8,HotSpot完全废除了方法区上的永久代,(JDK 8以前,HotSpot将GC使用永久代来实现方法区,因为容易造成内存溢出),在本地内存中实现了元空间,把JDK 7中永久代还剩余的内容(主要是类型信息)全部移动到了元空间中

元空间使用的是与堆不相连的本地内存区域,所以理论上系统内存有多大,元空间就有多大,不会出现永久代存在时的内存溢出问题。后面也会专门用一篇文章来介绍元空间的。

运行时常量池

Class文件中有一项是常量池表,用来存放编译器生成的各种字面量与符号引用,字面量包括了文本字符串,final,基本数据类型和其他,符号引用包括了类和结构的完全限定名,字段,方法的名称和描述符等。

这部分内容将会在类加载后存放到方法区的运行时常量池中。运行时常量池相对于Class文件常量池具有动态性,并非预置入Class文件常量池的内容才能进入运行时常量池,运行期间的新的常量也可以,一个栗子就是String类的intern()方法

直接内存

在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。

参考

  • [1] 深入理解Java虚拟机,周志明
  • [2] java方法区究竟存储了什么?



推荐阅读
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • 重入锁(ReentrantLock)学习及实现原理
    本文介绍了重入锁(ReentrantLock)的学习及实现原理。在学习synchronized的基础上,重入锁提供了更多的灵活性和功能。文章详细介绍了重入锁的特性、使用方法和实现原理,并提供了类图和测试代码供读者参考。重入锁支持重入和公平与非公平两种实现方式,通过对比和分析,读者可以更好地理解和应用重入锁。 ... [详细]
  • Java 11相对于Java 8,OptaPlanner性能提升有多大?
    本文通过基准测试比较了Java 11和Java 8对OptaPlanner的性能提升。测试结果表明,在相同的硬件环境下,Java 11相对于Java 8在垃圾回收方面表现更好,从而提升了OptaPlanner的性能。 ... [详细]
  • 本文整理了Java中org.gwtbootstrap3.client.ui.Icon.addDomHandler()方法的一些代码示例,展示了Icon.ad ... [详细]
  • 图片添加二维码水印教程
    本博客介绍一下用jdkawt实现图片加文字水印和图片水印的方法一、图片文字水印原来图片加上文字水印后图片二、图片加图片水印原来图片:水印图片:添加水印后的图片: ... [详细]
  • PHP输出缓冲控制Output Control系列函数详解【PHP】
    后端开发|php教程PHP,输出缓冲,Output,Control后端开发-php教程概述全景网页源码,vscode如何打开c,ubuntu强制解锁,sts启动tomcat慢,sq ... [详细]
  • 初识java关于JDK、JRE、JVM 了解一下 ... [详细]
  • 本文整理了常用的CSS属性及用法,包括背景属性、边框属性、尺寸属性、可伸缩框属性、字体属性和文本属性等,方便开发者查阅和使用。 ... [详细]
author-avatar
幽默的人生就是悲催基_129
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有