JVM运行时数据区域

文章目录

  • 内存结构
      • 程序计数器(寄存器)
      • 虚拟机栈
        • 局部变量表
          • 两类异常状况
        • 线程运行诊断
      • 本地方法栈
      • 方法区
      • 运行时常量池
        • 串池(StringTable)
          • 字符串的拼接
          • 串池的位置
          • StringTable垃圾回收
          • StringTable性能调优
      • 直接内存

内存结构

程序计数器(寄存器)

Java源代码不能被cpu直接执行,需要经过编译,编译成二进制的字节码,二进制字节码中的一行行代码就是jvm指令

Java跨平台技术就是靠这一条条jvm指令,对任何操作系统都是一致的

这些指令再经过解释器解释成机器码,机器码可以被cpu执行

程序计数器的作用就是在解释器解释jvm指令的过程中记住下一条jvm指令的执行地址
在物理上程序计数器是通过寄存器(cpu中读取最快的一个单元)实现的(因为读取地址是非常频繁的)

极小的一块内存

每条线程都需要一个独立的程序计数器(程序计数器是线程私有的)

是在jvm规范中,唯一一个不会存在内存溢出的区

当前线程所执行的字节码的行号指示器

字节码解释器通过改变计数器的值选取下一条要执行的字节码的指令

是程序控制流的指示器

虚拟机栈

  • 每个线程运行所需要的内存,称为虚拟机栈
  • 每个栈由栈帧构成,对应每次方法调用时所占的内存
  • 每个线程只能有一个活动栈帧,对应当前正在执行的那个方法

也是线程私有的,生命周期与线程相同,线程结束,栈结束,所以不存在垃圾回收问题

栈内存不是越大越好,栈的内存大了,线程数就少了,内存大了只能增快方法的递归调用

方法内局部变量是否具有线程安全问题:

如果这个变量是共享的,如static,就会有线程安全问题, 如果这个变量逃离了方法的作用范围,也会有线程安全问题

否则,不会有线程安全问题

每个方法被执行时,jvm会同步创建一个栈帧,用于存储局部变量表、操作数栈、动态连接、方法出口等信 息

**栈帧:**每个方法运行时需要的内存(如参数,局部变量,返回地址,这些都要提前分配内存)

8大基本类型,对象引用,实例方法

局部变量表
  • 存放了各种jvm基本数据类型,对象引用(reference类型),returnAddress类型,这些数据类型在局部变量表中的存储空间以局部变量槽(Slot),来表示。
  • 64位的long,double类型占用两个变量槽,其余数据类型占用一个。
  • 所需要的内存空间在编译期间完成分配,方法运行期间不会改变局部变量表的大小(指变量槽的数量)
两类异常状况
  • 如果线程请求的栈深度超过了虚拟机允许的深度(栈帧过多,栈帧过大),抛出StackOverflowError异常
  • 如果虚拟机栈容量可以动态扩展,当栈扩展时无法申请足够的内存抛出OutOfMemeoryError异常

HotSpot虚拟机的栈容量是不可以动态扩展的,所以在HotSpot上不会由于·虚拟机栈无法扩展而导致OutOfMemeoryError异常,但是如果线程申请栈空间失败,仍会出现OOM异常

线程运行诊断
  • cpu占用过多
  • 程序运行很长时间没有结果

本地方法栈

与虚拟机栈发挥作用非常相似,和虚拟机栈一样,也会在栈深度溢出和栈扩展失败时抛出异常StackOverflow,OOM

区别:

虚拟机栈为虚拟机执行Java方法服务,本地方法栈为虚拟机使用到的本地(Native)方法服务

VM options 控制堆内存大小为8mb -Xmx 8m

  • 虚拟机管理内存中最大的一块
  • 是被所有线程共享(堆中对象需要考虑线程安全问题)的一块内存区域,一个jvm只有一个堆内存,堆内存大小可以调节
  • 在虚拟机启动时创建
  • 唯一目的是存放对象实例,几乎所有对象实例都在这里分配内存
  • 垃圾收集器管理的内存区域,也被称为GC堆

从回收内存角度来看

现代垃圾收集器大部分都是基于分代收集理论设计的,如新生代,永久代等,而这些仅仅是一部分垃圾收集器的设计风格而已,不是虚拟机固有布局,也不是对堆的进一步细致划分

从分配内存角度看

所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区,用来提升对象分配时的效率

无论从哪个角度,堆中存储的都只能是对象的实例,将Java堆细分只是为了更好的回收内存,更快的分配内存

Java堆不需要连续的内存

Java堆既可以是固定大小的,也可以是可扩展的,目前主流的虚拟机都是按照可扩展来实现的,如果堆中没有内存完成实例分配,并且堆无法扩展时,将抛出OOM异常

方法区

  • 被所有线程共享

  • 静态变量,常量,类信息(构造方法,接口定义),运行时常量池存在方法区中,但是实例变量存在堆内存中和方法区无关(重点)

    static , final,Class模板,常量池

  • 方法区是堆的一个逻辑部分(关于他到底是不是堆的一部分,不同的jvm厂商实现方式不同),但是有个别名叫非堆,从而与Java堆区分开来

JDK8之前是使用永久代实现的方法区,考虑到HotSpot的发展,这种实现方式被逐步放弃,改为用本地内存来实现方法区

JDK7时,将原本放在永久代的字符串常量池,静态变量等移出

JDK8,完全废弃的永久代的概念,改用本地内存中实现的元空间,把JDK7中剩余的内容全部移到元空间中

和Java堆一样不需要连续的内存,可以选择固定大小和可扩展,甚至可以选择不实现垃圾收集

相对来说,方法区垃圾收集比较少见,这部分内存回收的目标是针对常量池的回收和对类型的卸载

JDK8前会导致永久代内存溢出

JDK8后会导致元空间内存溢出

运行时常量池

常量池:就是一张表,虚拟机指令根据这张常量表找到要执行的类名,方法名,参数类型,字面量等信息

  • 是方法区的一部分
  • 常量池是.class文件中的,当该类被加载,他的常量池信息就会放入运行时常量池,并把里面的符号地址变成真实的地址
串池(StringTable)

StringTable特性:

  • 常量池中的字符串仅仅是符号,只有用到时才变成对象

  • 利用串池的机制,来避免重复创建字符串对象

  • 字符串变量拼接原理是StringBuilder (1.8)

  • 字符串常量拼接原理是编译器优化

  • 可以用intern方法,主动将串池中还没有的字符串对象放入串池

    • 1.8将这个字符串对象放入串池时,如果有则不会放入,没有就将这个对象放入,最后返回串池中的对象
    • 1.6如果有不会放入,如果没有把对象复制一份放入串池,最后返回串池中的对象

    区别:1.8放的是堆中的地址,1.6放的是对象副本的地址

String对象的加载是延迟的,只有走到才会将对象放到串池

/**
 * @author gwj
 */
public class HelloWorld {
    public static void main(String[] args) {
        //常量池中的信息,运行时被加载到运行时常量池,这是a b ab都是常量池中的符号,还没有变成Java字符串对象
        String s1 = "a";
        String s2 = "b";
        String s3 = "ab";
    }
}

在这里插入图片描述

StringTable 是哈希表结构,不能扩容

字符串的拼接
public class HelloWorld {
    public static void main(String[] args) {
        //常量池中的信息,运行时被加载到运行时常量池,这是a b ab都是常量池中的符号,还没有变成Java字符串对象
        String s1 = "a";
        String s2 = "b";
        String s3 = "ab";
        String s4 = s1 + s2; //new StringBuilder().append("a").append("b").toString()
        					 //new String("ab")
        System.out.println(s3 == s4);
        //s3在串池中,s4在堆中,所以false
        //javac 在编译期间的优化,结果在编译期已确定为ab
        //而上一行代码中s1和s4是变量,只能在运行期间用StringBuilder动态拼接
        String s5 = "a" + "b";
    }
}

在这里插入图片描述

StringBuilder的toString源码,new了一个String对象

@Override
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}

在这里插入图片描述

从字节码中能看出,在执行String s4 = “a” + “b”时,生成字节码与String s3 = “ab”相同

串池的位置
  • JDK1.6时,StringTable在常量池中,常量池在方法区中,方法区使用永久代实现
  • JDK1.8时,StringTable从永久代转到了堆中(因为串池中存着大量字符串,放在永久代中使用效率低,且永久代垃圾回收较难触发
StringTable垃圾回收

当内存空间不足时,StringTable中那些没有被引用的字符串就会被回收

StringTable性能调优
  • 如果系统中字符串常量个数非常多,建议将StringTableSize调大些,减少哈希冲突,提高查找效率
  • 可以通过intern方法让字符串入池,从而减少重复字符串的个数,减少内存的占用

直接内存

  • 直接内存不是虚拟机运行时数据区的一部分,也不是定义的内存区域,是操作系统内存,但是也被频繁使用,也可能导致OOM异常

  • 不受jvm内存回收管理,直接内存的释放可以通过调用Unsafe对象的freeMemory方法

  • 常见于NIO操作中,用于数据缓冲区

  • JDK4中加入了NIO类,引入了一种基于通道和缓冲区的I/O方式

  • 可以使用Native函数直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,这样避免了在Java堆和Native堆中来回复制数据

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

blue beacon rssi 指纹室内定位数据集

数据集是开展实验的基础,搜集并分享。如果你有关于室内定位的问题,请联系博主。 namedatesetpapercommentBLEBeacon: A Real-Subject Trial Dataset from Mobile Bluetooth Low Energy Beaconshttps://github.com/dimisik/BLEBeacon-Datasethttps://arxi…

【云备份】业务处理

文章目录 1. 业务处理作用功能 2. 代码框架编写构造函数UpLoad ——文件上传请求ListShow —— 展示页面请求处理实现Download —— 下载请求的处理实现断点续传实现 1. 业务处理 作用 业务处理模块是对客户端的业务请求进行处理 功能 1.文件上传请求:备份客户端…

RK3568平台开发系列讲解(Linux系统篇)netlink 监听广播信息

** 🚀返回专栏总目录 文章目录 一、什么是netlink 机制二、netlink 的使用2.1、创建 socket2.2、绑定套接字2.3、接收数据沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍如何通过 netlink 监听广播信息。 一、什么是netlink 机制 Netlink 是 Linux 内核中…

反序列化漏洞详解(一)

目录 一、php面向对象 二、类 2.1 类的定义 2.2 类的修饰符介绍 三、序列化 3.1 序列化的作用 3.2 序列化之后的表达方式/格式 ① 简单序列化 ② 数组序列化 ③ 对象序列化 ④ 私有修饰符序列化 ⑤ 保护修饰符序列化 ⑥ 成员属性调用对象 序列化 四、反序列化 …

Stream

什么是Stream? 也叫Stream流,是jdk8开始新增的一套API,可以用来操作集合或者数组的数据 优势:Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或数组中的数据&am…

CTF-虚拟机-QEMU-前置知识-操作流程与源码阅读

文章目录 总览内存PCI设备PCI配置空间前64个字节对应源码Memorry空间的BARIO空间的BAR MMIOPMIOIspci访问PCI设备配置空间中的Memory空间和IO空间MMIOPMIO QQM(qemu object model)简洁概要将 TypeInfo 注册 TypeImpl:ObjectClass的初始化&…

新款任务悬赏拉新地推本地任务同城地区定位游戏试玩任务联盟众人帮威客兼职任务墙

新款任务悬赏拉新地推本地任务同城地区定位游戏试玩任务联盟众人帮威客兼职任务墙 源码开源无任何加密及授权 后端采用PHPTinkCMF 前端采用UniappVUE 网页端双端APP可封装小程序可对接公众号登录 采用原生混合框架,拒绝卡顿。 https://download.csdn.net/downl…

文件操作--IO

目录 ♫什么是文件 ♫文件路径 ♫文件类型 ♫文件的管理 ♪File的构造方法 ♪File的常用方法 ♫文件的内容操作 ♪InputStream ♪OutputStream ♪字符流读写文件 ♫Scanner与流对象 ♫什么是文件 文件在计算机里可以指“狭义”的文件(指硬盘上的文件和目录&…

第一百八十七回 DropdownButton组件

文章目录 1. 概念介绍2. 使用方法2.1 DropdownButton2.2 DropdownMenuItem 3. 示例代码4. 内容总结5. 经验分享 我们在 上一章回中介绍了"DropdownMenu组件"相关的内容,本章回中将介绍 DropdownButton组件.闲话休提,让我们一起Talk Flutter吧…

基于SpringBoot学生宿舍管理系统的设计与开发

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对学生宿舍信息管理混乱,出错率高,信息安全性差…

javaee实验:MVC 框架技术应用——URL 映射及方法参数的使用

目录 urlmvc框架mvc框架的设计mvc流程 实验目的实验内容实验过程创建项目创建项目结构编写代码简单测试一下 url 和 Hypertext 以及 HTTP 一样,URL 是 Web 中的一个核心概念。它是浏览器用来检索 web 上公布的任何资源的机制 URL 代表着是统一资源定位符&#xff…

OpenCV技术应用(6)— 暖色滤镜和冷色滤镜

前言:Hello大家好,我是小哥谈。本节课就手把手教大家如何将一幅图像转化成暖色滤镜和冷色滤镜,希望大家学习之后能够有所收获~!🌈 目录 🚀1.技术介绍 🚀2.暖色滤镜 🚀3.冷色滤…

每日一练:阿姆斯特朗数

1. 概述 阿姆斯特朗数(Armstrong number),也称为自恋数、自幂数(narcissistic number)、水仙花数,是指一个n位数(n≥3),它的每个位上的数字的n次幂之和等于它本身。换句话…

AVFormatContext协议层:理论与实战

文章目录 前言一、协议操作对象结构二、初始化 AVIOContext 函数调用关系三、avio 实战 1:打开本地文件或网络直播流1、示例源码2、运行结果①、解决方法 1②、解决方法 2 四、avio 实战 2:自定义 AVIO1、示例源码2、运行结果 五、avio 实战 3&#xff1…

Vivado版本控制

Vivado版本控制 如果您有幸进入FPGA领域,那么会遇到版本控制问题,本文讲解的是如何用git进行Vivado进行版本控制。 搭建Git环境 一 首先需要一个git环境,并选择一个托管平台(github,gitlab,gitee) Git下载地址&…

【广州华锐视点】广东3D展厅开发服务找广州华锐视点,打造未来展览新体验!

随着科技的不断发展,人们对于信息获取和传播的方式也在不断创新。传统的实体展览馆在空间、时间、地域等方面存在诸多限制,而3D数字展厅则为我们提供了一个全新的解决方案。广州华锐互动致力于为客户提供专业的3D数字展厅定制开发服务,让您的…

滑动平均窗口的定义,优点,缺点,以及目前的应用!!

文章目录 前言一、滑动平均窗口的优点二、滑动平均窗口的缺点三、滑动平均窗口的应用 前言 滑动平均窗口是一种数据处理方法,它以固定的窗口大小对数据进行移动,并在每个窗口内计算数据的平均值。这种方法主要用于平滑数据,减小数据波动的影…

鸿蒙开发学习笔记

快速入门 配置网络权限 1.打开项目的 module.json5 文件 2.在module 里面写下面代码 3.这样就可以使用网络图片了 4.模拟器上就可以正常显示网络图片了 5.官方文档有相吸说明 6. 华为官方编辑工具使用技巧(内置文档),鼠标移动到标签上&…

计算机网络扫盲(1)——因特网

一、概述 因特网是一个世界范围的计算机网络,即它是一个互联了遍及全世界数十亿计算设备的网络。大家对此应该并不陌生,我们身边有着不计其数的计算机设备被接入了因特网,如今计算机网络这个术语似乎已经有点过时了,用因特网的术语…

STM32-GPIO

一、GPIO简介 GPIO(General Purpose Input Output)通用输入输出口 可配置8种输入输出模式 引脚电平:0V~3.3V,部分引脚可容忍5V 输出模式下:可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输…