JVM基础(内存结构)

文章目录

  • 内存结构
    • JAVA堆
    • 方法区 (Method Area)
      • 运行时常量池(Runtime Constant Pool)
    • 虚拟机栈 (Java Virtual Machine Stack)
    • 本地方法摘栈(Native Method Stacks)
    • 程序计数器(Program Counter Register)
    • 直接内存(Direct Memory)
  • JVM参数设置

内存结构

可称为java的自动内存管理机制。
在这里插入图片描述
三大部分:

  • 堆内存
  • 方法区
  • 栈内存

现在jdk默认使用的是 Hot-Spot 虚拟机。
在这里插入图片描述

JAVA堆

堆是虚拟机中最大的一块内存,被所有线程共享的内存区域.
唯一作用就是: 放New出来的对象,几乎所有对象都在这里面分配内存1(以后说不定)。

堆可以实现固定的大小也可以扩展(通过参数-Xmx和-Xms设定)扩展失败就会爆OOM异常

堆分两个区老年代和新生代 默认比例 young 1:2 oid 通过:–XX:NewRatio

新生代又分为Eden区和2个Survivor区(From Survivor 和 To Survivor)
默认的,Eden : from : to = 8 : 1 : 1
通过 –XX:SurvivorRatio来设定

深入理解java虚拟机:
Java 堆是垃圾收集器管理的内存区域,因此一些资料中它也被称作“GC堆”(Garbage Collected Heap,幸好国内没翻译成“垃圾堆”)。从回收内存的角度看,由于现代垃圾收集器大部分都是基于分代收集理论设计的,所以Java堆中经常会出现“新生代”“老年代”“永久代”“Eden空间”“From Survivor空间”“To Survivor空间”等名词,这些概念在本书后续章节中还会反复登场亮相,在这里笔者想先说明的是这些区域划分仅仅是一部分垃圾收集器的共同特性或者说设计风格而已,而非某个Java虚拟机具体实现的固有内存布局,更不是《Java虚拟机规范》里对Java堆的进一步细致划分。不少资料上经常写着类似于“Java虚拟机的堆内存分为新生代、老年代、永久代、Eden、Survivor……”这样的内容。在十年之前(以G1收集器的出现为分界),作为业界绝对主流的HotSpot虚拟机,它内部的垃圾收集器全部都基于“经典分代” 2来设计,需要新生代、老年代收集器搭配才能工作,在这种背景下,上述说法还算是不会产生太大歧义。

但是到了今天,垃圾收集器技术与十年前已不可同日而语,HotSpot里面也出现了不采 用分代设计的新垃圾收集器,再按照上面的提法就有很多需要商榷的地方了。

如果从分配内存的角度看,所有线程共享的Java堆中可以划分出多个线程私有的分 配缓冲区(Thread Local Allocation Buffer,TLAB),以提升对象分配时的效率。不过无 论从什么角度,无论如何划分,都不会改变Java堆中存储内容的共性,无论是哪个区 域,存储的都只能是对象的实例,将Java 堆细分的目的只是为了更好地回收内存,或 者更快地分配内存。在本章中,我们仅仅针对内存区域的作用进行讨论,Java堆中的上 述各个区域的分配、回收等细节将会是下一章的主题。

方法区 (Method Area)

jdk8之前又称永久代,同堆一样是一个线程共享的内存区域, 存储虚拟机加载的类信息、常量、静态变量,即时编译器编译后的代码缓存等数据。

深入理解java虚拟机:
虽然《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫
作“非堆”(Non-Heap),目的是与Java堆区分开来。

JDK8之前的HotSpotJVM,存放这些”永久的”的区域叫做“永久代(permanent
generation)”。永久代是一片连续的堆空间,在JVM启动之前通过在命令行设
置参数-XX:MaxPermSize 来设定永久代最大可分配的内存空间,默认大小是64M
(64位JVM默认是85M)。

jdk8之后叫Metaspace(元空间)其实和之前的概念是一样的

从 Hotspot JVM 中删除永久代,因此需要调整永久代的大小。

Class metadata, interned Strings and class static variables will be moved from the permanent generation to either the Java heap or native memory.

The code for the permanent generation in the Hotspot JVM will be removed.
Application startup and footprint will not regress more than 1% as measured by a yet-to-be-chosen set of benchmarks.

运行时常量池(Runtime Constant Pool)

方法区的一部分
用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。
-会把由符号引用翻译出来的直接引用也存储在运行时常量池中。

运行时常量池没有格式上的细节规范,没一个虚拟机都可以自己实现这一个内存区域,相对于Class文件的常量池另一个特征是动态性,

Java语言并不要求常量一定只有编译期才能产生,也就是说,并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可以将新的常量放入池中,这种特性被开发人员利用得比较多的便是String类的 intern()方法。

也会报oom异常

虚拟机栈 (Java Virtual Machine Stack)

常说的栈 内存就是这个玩意
线程私有

生命周期和线程一样

创建线程的时候也会创建虚拟机栈

java程序执行时,每一个方法都会 创建 一个栈帧 放到虚拟机栈中 通过压栈出栈的方式进行方法调用

栈帧又分为一下几个区域:局部变量表、操作数栈、动态连接、方法出口等

我们所说的变量存在栈中,这句话说的不太严谨,应该说局部变量存放在java 虚拟机栈的局部变量表中。
java 的8中基本类型的局部变量的值存放在虚拟机栈的局部变量表中,如果是引用型的变量,则只存储对象的引用地址。

局部变量表存放了编译期可知的各种Java虚拟机基本数据类型(boolean、byte、
char、short、int、 float、long、double)、对象引用(reference类型,它并不等同于对象
本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或
者其他与此对象相关的位置)和returnAddress 类型(指向了一条字节码指令的地址)。

这些数据类型在存储空间以局部变量槽(Slot)来表示,64位长度的long和double占两个Slot,
其余占一个
局部变量的内存空间在 编译期间产生并分配

经常有人把Java内存区域笼统地划分为堆内存(Heap)和栈内存(Stack),这种划
分方式直接继承自传统的C、C++程序的内存布局结构,在Java语言里就显得有些粗糙
了,实际的内存区域划分要比这更复杂。

可能出现的异常就是OutOfMemoryError ,如果可以动态扩展,但是还是不够就会报OutOfMemoryError

本地方法摘栈(Native Method Stacks)

与虚拟机栈的作用是非常相似的

  • 区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务
  • 而本地方法栈则是为虚拟机使用到的Native方法服务。

《Java虚拟机规范》对本地方法栈中方法使用的语言、使用方式与数据结构并没有任何强制规定,因此具体的虚拟机可以根据需要自由实现它,甚至有的Java虚拟机(譬如Hot-Spot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈也会在栈深度溢出或者栈扩展失败时分别抛出StackOverflowError和OutOfMemoryError 异常。

程序计数器(Program Counter Register)

在虚拟机的概念模型中计数器: 记录当前线程执行程序的位置,改变计数器的值来确定执行的下一条指令,
比如循环、分支、方法跳转、异常处理,线程恢复都是依赖程序计数器来完成。

Java 虚拟机多线程是通过线程轮流切换并分配处理器执行时间的方式实现的。

为了线程切换能恢复到正确的位置,每条线程都需要一个独立的程序计数器,所以它是线程私有的。(在任何一个确定的时刻,处理器的一个内核中只会执行一个线程的指令,)

如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;
如果正在执行的是Native方法,这个计数器值则为空(Undefined)。
此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError(内存溢出)情况的区域。

直接内存(Direct Memory)

这个不是虚拟机的内存,但是也会检查使用而且还会报oom异常

在JDK 1.4中新加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的 DirectByteBuffer对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。

这个内存不受java堆的限制,但受物理主机限制
这个动态控制需求大于你实际物理主机的情况下肯定会报oom了,

显然,本机直接内存的分配不会受到Java堆大小的限制,但是,既然是内存,则肯
定还是会受到本机总内存(包括物理内存、SWAP分区或者分页文件)大小以及处理器
寻址空间的限制,一般服务器管理员配置虚拟机参数时,会根据实际内存去设置-Xmx
等参数信息,但经常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括
物理的和操作系统级的限制),从而导致动态扩展时出现OutOfMemoryError异常。

JVM参数设置

  • -Xms设置堆的最小空间大小。
  • -Xmx设置堆的最大空间大小。
  • -Xmn:设置年轻代大小
  • -XX:NewSize 设置新生代最小空间大小。
  • -XX:MaxNewSize 设置新生代最大空间大小。
  • -XX:PermSize 设置永久代最小空间大小。
  • -XX:MaxPermSize 设置永久代最大空间大小。
  • -Xss设置每个线程的堆栈大小
  • -XX:+UseParallelGC:选择垃圾收集器为并行收集器。此配置仅对年轻代有效。即上述配置下,年轻代使用并发收集,而年老代仍旧使用串行收集。
  • -XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。

Xmx3550m:设置 JVM 最大可用内存为3550M。
-Xms3550m:设置 JVM 促使内存为3550m。此值可以设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小+年老代大小+持久代大小。
持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值
对系统性能影响较大,官方推荐配置为整个堆的3/8。-Xss128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前
每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统
对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000
左右。

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

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

相关文章

交易的人生就是对未来不断的挑战!

在这个充满不确定性的市场中,我们每个人都渴望找到一条通往成功的路径。在Eagle Trader交易员中,有一位资深交易者,他不仅对交易有着不同寻常的执着和热爱,而且他的真诚见解和独到的交易哲学,可能会触动你的心弦。他的…

尚硅谷-react教程-求和案例-@redux-devtools/extension 开发者工具使用-笔记

## 7.求和案例_react-redux开发者工具的使用(1).npm install redux-devtools/extension(2).store中进行配置import { composeWithDevTools } from redux-devtools/extension;export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk))) src/redux/s…

OpenCV系列教程六:信用卡数字识别、人脸检测、车牌/答题卡识别、OCR

文章目录 一、信用卡数字识别1.1 模板匹配1.2 匹配多个对象1.3 处理数字模板1.4 预处理卡片信息,得到4组数字块。1.5 遍历数字块,将卡片中每个数字与模板数字进行匹配 二、人脸检测2.1人脸检测算法原理2.2 OpenCV中的人脸检测流程 三、车牌识别3.1 安装t…

一行代码,实现请假审批流程(Java版)

首先画一个流程图 测试流程图 activiti 项目基础配置 activiti 工作流引擎数据库设计 工作流引擎API 介绍 什么是BPMN流程图 工作流引擎同类对比 继续学习方向 总结 工作流审批功能是办公OA系统核心能力,如果让你设计一个工作流审批系统,你会吗…

SDK5(note中)

在原有SDK5(note上)里的代码上添加了 timer的消息 LRESULT OnCreate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {OutputDebugString(_T("[11syy]WM_CREATE\n"));//创建一个计时器SetTimer(hwnd, 1, 1000, nullptr);return TRUE; }LRESULT OnClese(HWND …

全星魅 北斗三号船载终端的优势和领域利用

QM43BS型北斗三号船载终端:开启航海通信与定位新时代 在当今这个信息化高速发展的时代,航海领域对于通信与定位技术的需求愈发迫切。深圳市全民北斗科技有限公司,作为北斗技术应用领域的佼佼者,针对数传通信和位置服务应用&#x…

Python 实现深度学习模型预测控制--预测模型构建

链接:深度学习模型预测控制 链接:WangXiaoMingo/TensorDL-MPC: DL-MPC(deep learning model predictive control) is a software toolkit developed based on the Python and TensorFlow frameworks, designed to enhance the performance of tradition…

你了解kafka消息队列么?

消息队列概述 一. 消息队列组件二. 消息队列通信模式2.1 点对点模式2.2 发布/订阅模式 三. 消息队列的优缺点3.1 消息队列的优点3.2 消息队列的缺点 四. 总结 前言 这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者&…

Android Junit 单元测试 | 依赖配置和编译报错解决

问题 为什么在依赖中添加了testImplement在build APK的时候还是会报错?是因为没有识别到test文件夹是test源代码路径吗? 最常见的配置有: implementation - 所有源代码集(包括test源代码集)中都有该依赖库.testImplementation - 依赖关系仅在test源代码…

理解磁盘结构---CHS---LAB---文件系统

1,初步了解磁盘 机械磁盘是计算机中唯的一个机械设备, 特点是慢,容量大,价格便宜。 磁盘上面的光面,由数不清的小磁铁构成,我们知道磁铁是有n/s极的,这刚好与二进制的&…

selenium脚本编写及八大元素定位方法

selenium脚本编写 上篇文章介绍了selenium环境搭建,搭建好之后就可以开始写代码了 基础脚本,打开一个网址 from selenium import webdriver driver webdriver.Chrome()#打开chrome浏览器 driver.get(https://www.baidu.com) #打开百度 打开本地HTML文件 上篇…

利用Kubernetes原生特性实现简单的灰度发布和蓝绿发布

部分借鉴地址: https://support.huaweicloud.com/intl/zh-cn/bestpractice-cce/cce_bestpractice_10002.html 1.原理介绍 用户通常使用无状态负载 Deployment、有状态负载 StatefulSet等Kubernetes对象来部署业务,每个工作负载管理一组Pod。以Deployment为例&#x…

Macos m系列芯片环境下安装python3以及mysqlclient流程以及遇到的一系列问题

最近升级了生产力,换了m3的mbp,迁移项目的时候遇到的一系列python mysqlclient的环境问题,这里总结记录一下。 设备:Macbook Pro m3系统:macos Sonoma 14.6最终成功的python版本:Python3.9.1最终系统环境下…

STL-常用容器-list

1list基本概念 **功能:**将数据进行链式存储 链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成:链表由一系列结点组成 结点的组成:一个是存储…

基于django的志愿者社团管理系统

大家是不是常常遇到校园社团活动组织混乱、统计繁琐的困扰?其实我以前在做毕业设计的时候也头疼这些问题。后来,我们开发了一个基于Django的志愿者社团管理系统,可以帮你轻松解决这些麻烦!📌 🚀 核心功能模…

Opensearch集群部署【docker、服务器、Helm多种部署方式】

操作系统兼容性 我们建议在 Red Hat Enterprise Linux (RHEL) 或使用systemd的基于 Debian 的 Linux 发行版上安装 OpenSearch ,例如 CentOS、Amazon Linux 2 和 Ubuntu Long-Term Support (LTS)。OpenSearch 应该适用于大多数 Linux 发行版,但我们只测…

Java题集练习4

Java题集练习4 1 异常有什么用? 用来找到代码中产生的错误 防止运行出错2 异常在java中以什么形式存在? 异常在java中以类的形式存在,分为运行时异常和编译期异常,他们都在类Exception中3 异常是否可以自定义?如何自…

衡石分析平台系统分析人员手册-导入图表库图表

导入图表库图表​ 本文讲述在仪表盘中如何使用图表库图表,如果您还不了解图表库,请先点击链接了解它的功能和作用。 在数据集市中建立图表库后,分析人员可以在应用创作中引用图表库图表,快速的进行数据分析工作。 导入图表库图…

【建造&机械】木材运输车辆检测系统源码&数据集全套:改进yolo11-GhostHGNetV2

改进yolo11-SPPF-LSKA等200全套创新点大全:木材运输车辆检测系统源码&数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.10.28 注意:由于项目一直在更新迭代,上面“1.图片效果展示”和“2.视频效果展示”展示的系统图片…

ubuntu 20.04编译驱动报gcc-12 not found错误

最近在自己安装的Ubuntu 系统上编译自定义驱动,发现无法编译.ko,错误如下: 按照如下操作,发现可以解决,记录下,主要是Ubuntu缺少g-12的包 安装包以后发现可以正常编译