【JVM】JVM内存模型与操作系统内存模型(二)

news2024/9/24 21:21:58

JVM内存模型与操作系统内存模型

在这里插入图片描述

本地方法栈

与虚拟机栈发挥的作用是相似的,他们之间的区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。在虚拟机规范中对本地方法栈中使用、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。甚至有的虚拟机 比如(SUn HotSpot虚拟机)直接就把本地方法栈和虚拟机栈合二为一。与虚拟机栈一样,本地方法栈区域也会抛出StackOverflowError和OutOfMemoryErr异常
调用JNI程序(安卓需要操作硬件),Java没有办法直接操作硬件。只能用C/C++汇编调用需要加载动态链接库(Sytem.loading())手动加载jar包

// 点亮屏幕
public static native void light();

这些动态链接库下面是一些操作系统内核中的驱动。在做嵌入式的驱动硬件中,之前是嵌入Linux内核,现在是嵌入Android系统。
Java通过JNI调用C/C++动态链接库需要的栈,随着socket的发展,JNI技术已经用得非常非常少了

对于大多数应用来说,Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有对象实例以及数组都要在堆上分配,但是随着JIT编译器的发展与逃逸分析技术逐渐成熟,栈上分配、标量替换优化技术将会导致一些微妙的变化发生,所有的对象都分配在堆上也渐渐变得表示那么"绝对"了。Java堆是垃圾收集器管理的主要区域,因此很多时候也被称做"GC堆"(Garbage Collected Heap,幸好国内没有翻译成"垃圾堆"),从内存回收的角度来看,由于现在收集器基本都采用分代收集算法,所以Java堆中还可以细分:新生代和老年代:再细致一点的有Eden空间、From Survivor空间、To Survivor空间等。从内存分配的角度来看,线程共享的Java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB).不过无论如何划分,都与存放内容无关,无论哪个区域,存储的都仍然是对象实例,进一步划分的目的是为了更好地回收内存,或者更快地分配内存。
根据Java虚拟机规范的规定,Java堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx和-Xms控制)。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出OutOfMemoryError异常。
堆区min:1/64 物理内存 max:1/4物理内存

为什么老年代空间>新生代空间? 因为老年代要存储的东西比新生代多

  • 1.GC大于15的对象(跟对象头有关,4个bit)
  • 2.空间担保机制
  • 3.动态年龄判断机制:新生代没有足够的空间存放,
    为了能更好地适应不同程序的内存状况,虚拟机并不是永远地要求对象地年龄必须达到了MaxTenuringThreshold才能晋升老年代,如果在Survivor空间中相同年龄所有对象大小地综合大于Survivor空间地一般,年龄大于或等于该年龄地对象就可以直接进入老年代,无需等到MaxTenuringThreshold中要求的年龄。
  • 4.大对象
    所谓的大对象是指,需要大量连续内存空间的Java对象,最典型的大对象就是那种很长的字符串以及数组。大对象对虚拟机的内存分配来说就是一个坏消息(比遇到一个大对象更加坏的消息就是遇到一群"朝生夕死"的"短命大对象",写程序的时候应当避免),经常出现大对象容易导致内存还有不少空间时就提前触发垃圾收集以获取足够的连续空间来"安置"它们。虚拟机提供了一个参数,大于这个参数的对象直接在老年代分配。这样做的目的是避免在Eden区及两个Survivor区之间发生大量的内存复制
    内存模型中最核心的区域,也是JVM调优重点关注的区域

对象的创建

在这里插入图片描述

DCL中单例对象的创建为什么要加volatile?
如果在ns级别的超高并发是需要加volatile关键字的,这个关键字会禁止指令重排,因为CPU是会乱序执行这些指令的。如下指令
接下来我们看下一个对象的创建流程
0 new #2
1.堆区申请了内存(不完全对象)构造方法还未执行
2.内存地址压入栈
3 dup duplicate
1.赋值栈顶元素

为什么要复制?
因为接下来调用init非静态方法,但是this指针还是空的,所以需要把栈顶元素弹出去,给this指针赋值,然后再把元素压入栈
2.再次压入栈
4 invokespecial #3 方法
this指针
this = null

执行方法分为两步:
1.构建环境会涉及到创建栈帧、传参、保存现场。给this指针赋值,记录方法的执行之前的位置
2.执行

7 astore_1
1.pop出元素:对象的指针
2.赋值给index=1的位置的变量(局部变量)

JVM内存模型的设计与GC收集器有很大关系

G1之前是新生代 + 老年代
之后划分2048个块,每个块大小为2M,基于Region模型
新生代中在一轮GC之后,90~95%的对象都会被回收,采用复制的话,避免了内存整理,操作比较简单。
分代+复制算法:为了保证内存使用的高效性
标记-清楚算法: 会有碎片化问题
标记-整理算法:整理算法 内存合并算法 耗费CPU,

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

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

相关文章

7.添加购物车以及完善导航条跳转

添加购物车 一、引言二、前端2.1引入轻组件2.2为图片添加点击事件2.3创建addShoppingCart函数 三、后端四、运行效果五、导航条跳转 一、引言 在前几篇文章中,我们一步一步慢慢的实现了项目的建立,从数据库获取数据显示在页面,商品大图查看&…

08 内置函数

目录 日期函数字符串函数数学函数其他函数 1. 日期函数 函数名称描述current_date()当前日期current_time()当前时间current_timestamp()当前时间戳date(datetime)返回datetime参数的日期部分date_add(da…

Java 继承Thread 和 实现Runnable的关联

在java中创建线程的最常用的两种方法 1.继承Thread类 2.继承Runnable接口 但是实现了Runnable接口之后,这个类不能自己启动,需要将其传递给一个Thread实例对象,然后通过Thread对象的start() 方法进行启动,因为只有Thread类中的 …

【系统架构设计】软件架构设计(1)

【系统架构设计】软件架构设计(1) 软件架构概述架构需求与软件质量属性软件架构风格数据流风格批处理序列管道-过滤器2者风格比较 仓库风格--黑板系统 层次系统架构风格二层及三层C/S架构风格MVCMVP 面向服务的架构 软件架构概述 基于架构的软件开发模型…

无心剑中译莎士比亚《吾爱稀罕胜天仙》

莎士比亚十四行诗第130首 Sonnet 130 吾爱稀罕胜天仙 My mistress’ eyes are nothing like the sun; Coral is far more red than her lips’ red; If snow be white, why then her breasts are dun; If hairs be wires, black wires grow on her head. I have seen roses d…

C++相关概念和易错语法(29)(lambda、function、bind)

1.lambda lamba表达式本质是匿名函数 书写格式:[ 捕捉列表 ] ( 参数 ) mutable -> 返回值 { 函数体 } 下面我会由简到难分享lambda的用法和它的理解 (1)基本使用和理解 我们先来看一段代码 我认为第一次看这个表达式应该还是能够…

LeetCode.55.跳跃游戏(贪心算法思路)

题目描述: 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 输…

为什么大公司不愿意使用 Python 作为 Web 后端开发语言?

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storm…

使用uart串口配置TMC2209模块

串口配置的优点: 通过串口助手配置TMC2209的寄存器实现转速,方向,细分数等寄存器设置。最大细分可达256。 TMC2209串口配置数据发送格式: 通过数据手册可知,TMC2209写入数据需要发送64位16进制。 前面0~7位是同步保…

OpenStack云计算平台实战

项目一 任务一 了解云计算 目前主流的开源云计算平台如下: OpenStack。OpenStack是一个提供IAAS开源解决方案的全球性项目,由Rackspace公司和NASA共同创办,采用了Apache2.0许可证,可以随意使用。OpenStack并不要求使用专门的硬…

“走进孔子博物馆 赓续千年乐章”孔乐古筝专场音乐会圆满成功!

2024年8月11日下午,备受期待的“走进孔子博物馆 赓续千年乐章”孔乐古筝专场音乐会在孔子博物馆隆重举行。此次音乐会不仅吸引了众多古筝艺术爱好者前来观看,更是一次将中华传统文化精髓与现代艺术相结合的盛会。现场座无虚席,观众朋友们共同…

C语言基础(十三)

指针的用法&#xff1a; 测试代码1&#xff1a; #include "date.h" #include <stdio.h> #include <stdlib.h> int main() { int time getTime();int n 3, m 4; // 使用malloc函数动态分配n行的指针数组&#xff0c;并将其赋值给二级指针arr。…

链表的插入操作——CSP-J1真题详解

【题目】 假设有一个链表的节点定义如下: struct Node { int data; Node* next; }; 现在有一个指向链表头部的指针&#xff1a;Node* head。如果想要在链表中插入一个新的节点&#xff0c;其成员 data 的值为 42&#xff0c;并使新节点成为链表的第一个节点&#xff0c;下面…

LLM和VLM算法常见面试题

LLM相关问题&#xff1a; Bert和GPT的区别 Bert和GPT是两种不同类型的自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;具有一些重要的区别。 模型架构&#xff1a;Bert是基于Transformer架构的模型&#xff0c;它是一个预训练的双向编码器。GPT也是基于Transformer…

【最大的和】

题目 思路 最大序列和的一般做法 dp前缀最大值 dp尾缀最大值 枚举分界点 代码 #include <bits/stdc.h> using namespace std;const int N 5e410; int a[N]; int um[N], dm[N], s; int main() {int t;cin >> t;um[0] INT_MIN;while(t--){int n;cin >> …

【Linux操作系统】进程间通信(1)

目录 一、认识进程间通信二、匿名管道三、命名管道 一、认识进程间通信 进程间不能直接传递数据&#xff0c;因为进程具有独立性&#xff0c;直接传递会破坏进程的独立性。 进程间通信是什么&#xff1f; 一个进程把自己的数据交给另一个进程。 为什么要有进程间通信&#xf…

ThreadLocal解惑

目录 1、ThreadLocal是什么? 2、ThreadLocal实现原理 3、设置线程变量的2种方式 4、关于ThreadLocal的内存泄漏问题 5、使用过程中的注意事项和误区 1、ThreadLocal是什么? 比较书面的回答&#xff1a; 类如其名&#xff0c;线程本地变量。当使用 ThreadLocal 维护变量时…

防爆巡检机器人:工业安全领域的璀璨明星

在当今快速发展的工业领域&#xff0c;安全与效率是企业追求的双核动力。特别是在石油、化工、钢铁冶金、燃气等高风险、高爆炸性的行业中&#xff0c;如何确保生产环境的绝对安全&#xff0c;同时提升巡检效率&#xff0c;成为了企业亟需解决的重大课题。正是在这样的背景下&a…

leetcode 438 找到字符串中所有字母异位词

leetcode 438 找到字符串中所有字母异位词 正文 正文 本题和 leetcode 49 字母异位分词 有些类似&#xff0c;只是 49 题中要求我们找出所有的异位词并进行存储&#xff0c;而本题我们只需要找出异位词对应的索引值。因此&#xff0c;我们无需用到字典&#xff0c;只需使用列表…

理解线程 ID 和 LWP

序言 在不同的系统中&#xff0c;为了更好地管理用户可能会采取不同的编号。比如在学校的教务系统中&#xff0c;管理学生使用的是学号&#xff1b;但是在住宿系统中&#xff0c;为了更加方便的获取一个学生的寝室信息&#xff0c;可能会采取结合你是哪一栋&#xff0c;哪一层&…