3-虚拟机篇

news2024/10/1 22:35:33

一.java JVM 的内存结构

内存:按线程类型分两类

线程共享:

  1. 方法区:存放类的信息
  2. 堆:存放java对象的信息

线程私有:

  1. java虚拟机栈:存放java方法、方法参数和局部变量
  2. 程序计数器:记录程序执行到几行

执行引擎

  1. 解释器:把class 字节码代码解释成机器码,对同一行代码反复解释,比如调用同一个方法多次,就会被解释多次。
  2. JIT即时编译器:把热点代码解释成机器代码,并且缓存起来。
    2.1热点判定的方式有两种:采样热点探测、计数器探测。判定某段代码是否为热点代码,是否要触发即时编译的这种行为称为“热点探测”

二.哪些部分会出现内存溢出

除了程序计数器外,方法区、堆、栈、本地方法栈都会出现内存溢出。
内存溢出分为两种情况:

  1. OutOfMemoryError

    • 堆内存耗尽- 对象越来越多,又一直在使用,不能被垃圾回收
    • 方法区内存耗尽- 加载的类越来越多,很多框架都会在运行期间动态产生新的类
    • 虚拟机栈累积- 默认每个线程最多会占用1M内存,线程个数越来越多,而 又长时间运行不销毁时
  2. StackOverflowError

    • 虚拟机栈内部- 方法调用次数过多,比如递归错误,无限制的运行,消耗掉线程内的1M内存。

方法区与永久代、元空间之间的关系

方法区是规范,永久代和元空间都是对方法区的实现。

  1. 方法区是JVM规范中定义的一块内存区域,用来存储类元数据、方法字节码、即时编译器需要的信息等

  2. 永久代是Hotspot虚拟机对JVM规范的实现(1.8之前)

  3. 元空间是Hotspot虚拟机对JVM规范的实现(1.8之后),使用本地内存作为这些信息的存储空间

JVM内存参数

对于JVM内存配置参数:

  • -Xmx10240m(最大内存数10G)
  • -Xms10240m(最小内存数10G)
  • -Xmn5120m(新生代5G)
  • -XX:SurvivorRatio=3其最小内存值和Survivor区总大小分别是
  • -Xss 线程的内存 linux 64位默认是1M

JVM垃圾回收算法

  1. 标记清除(都不用了)CMS,在最新的JVM虚拟机中已经废弃了
    分为标记阶段,和清除阶段。
    标记阶段先找到根对象,一定不能回收的对象。例如:局部变量引用的对象,正在被使用或者,静态变量引用的对象。沿着根对象的引用链,找到被引用的对象,标记这些对象。
    清除阶段:没有标记的对象直接清除就好了。
    缺点:标记清除,会导致内存碎片化,内存不连续

  2. 标记整理(适用于老年代垃圾回收)
    标记阶段:沿着根对象的引用链,找到被引用的对象,标记这些对象。
    整理阶段:移动存活对象到一边,解决内存碎片化,不连续的问题
    在这里插入图片描述

  3. 标记复制(适用于新生代代垃圾回收)
    标记阶段:沿着根对象的引用链,找到被引用的对象,标记这些对象。
    复制阶段:把存活对象复制到空闲区域,直接清理旧的区域就好了
    在这里插入图片描述
    缺点:占用内存多,经常用于新生代的内存空间。不适合老年代

说说GC 和 分代回收算法!!!!!

  • 1.Gc的目的在于实现无用对象的内存自动释放,减少内存碎片、加快内存分配速度

  • 2.GC要点

    • 1.回收区域是堆内存,不包括虚拟机栈,在方法调用结束会自动释放方法占用内存
    • 2.判断无用对象,使用可达性分析算法,三色标记法标记存活对象,回收未标记对象
    • 3.GC具体的实现称为垃圾回收器常见的垃圾回收器
    • 4.GC大都采用了分代回收思想,理论依据是大部分对象朝生夕灭,用完立刻就可以回收,另有少部分对象会长时间存活,每次很难回收,根据这两类对象的特性将回收区域分为新生代老年代,不同区域应用不同的回收策略
    • 5.根据GC的规模可以分成Minor Gc(新生代发生了垃圾回收),Mixed GC(老年代发生了垃圾回收),Full GC(时间比较长)
  • 3.分代回收

    • 1.伊甸园eden,最初对象都分配到这里,与幸存区合称为新生代
    • 2.幸存区survivor ,当伊甸园内存不足,回收后的幸存对象到这里,分成from 和 to ,采用标记复制算法
    • 3.老年代old,当幸存区对象熬过几次回收(最多15次),晋升到老年代(幸存区内存不足或大对象会导致提前晋升)
      在这里插入图片描述
  • 4 GC规模

    • 1.Minor GC 发生在新生代的垃圾回收,暂停时间短
    • 2.Mixed GC 新生代+ 老年代部分区域的垃圾回收,G1回收机器特有
    • 3.Full GC 老年代完整垃圾回收,暂停时间长,应尽力避免

三色标记与并发漏标问题

  1. 用三种颜色记录对象的标记状态

    • 1.黑色 - 已标记====>沿着 根对象的引用链,已经找到这个对象了,并且内部的其他引用已经完成了,就标记黑色
    • 2.灰色 - 标记中 ====>沿着 根对象的引用链,已经找到这个对象了,但是内部还有其他引用未完成了,就标记灰色
    • 3.白色 - 还未标记 ====>未被处理的都是白色标记
  2. 漏标问题-记录了 标记过程中变化 来解决漏标问题

    • 1.incremental Update(增量更新) 只要赋值发生,被赋值的对象就会被记录,重新标记成灰色。然后再做一遍处理,重新标记。
    • 2.Snapshot at the Beginning,SATB
      • 1.新增加对象会被记录
      • 2.被删除引用关系的对象也被记录

几个重要的垃圾处理器

  1. Parallel GC特点有如下
    • 1.eden内存不足发生Minor GC,标记复制 STW
    • 2.old内存不足发生Full GC,标记整理STW
    • 3.注重吞吐量
    • 4.虽然会暂停,但是会多个线程并行执行垃圾回收,所以时间比较短
  2. ConcurrentMarkSweep GC
    • 1.old 并发标记,重新标记时需要STW,并发清除
    • 2.Failback Full GC 并发失败,清除速度 < 对象产生的速度,就会并发失败,就会触发 Full GC
    • 3.注重响应时间
  3. G1 GC 从JDK9开始作为默认GC
  • 1.响应时间与吞吐量兼顾
  • 2.划分多个区域,每个区域都可以充当eden,survivor,old,humongous(存放大对象的区域)
  • 工作流程可以分为3个阶段
    • 1.新生代回收:eden内存不足,标记复制STW,复制到survivor,如果幸存对象到达了晋升阈值,就复制到老年代
    • 2.并发标记:old在堆内存中的占比超过45%,触发并发标记,重新标记时需要STW
    • 3.混合收集:并发标记完成,开始混合收集,参与复制的有eden、survivor、old,其中old会根据暂停时间目标,选择部分回收价值高(存活对象少)的区域,复制时STW
    • 4.Failback Full GC

项目中什么情况下会出现内存溢出,怎么解决的

  1. 误用线程池导致的内存溢出
//	案例1 主要是由于等待队列成撑爆了内存
public class TestThreadPool {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        while (true){
            executor.submit(()->{
                try {
                    LoggerUtils.get().debug("send sms");
                    TimeUnit.SECONDS.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}
主要是由于等待队列成撑爆了,不要用工具类创建线程池,自己调用 ThreadPoolExecutor ,控制拒绝策略和线程数上限
//	由于线程数没有上限,导致的内存溢出
public class TestThreadPool {
    public static void main(String[] args) {
        case2();
    }

    static AtomicInteger c = new AtomicInteger();
    private static void case2(){
        ExecutorService executor = Executors.newCachedThreadPool();
        while (true){
            System.out.println(c.incrementAndGet());
            executor.submit(()->{
                try {
                    TimeUnit.SECONDS.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

  1. 查询数据量太大导致的内存溢出

  2. 动态生成类过多导致的内存溢出

类加载过程、双亲委派机制

  • 类加载分为三个阶段
    1. 加载
      • 1.将类的字节码载入方法区,并创建类.class对象
      • 2.如果此类的父类没有加载,先加载父类,接口也是一样的。spring bean 也是一样的,创建当前bean时,先创建其依赖的bean
      • 3.加载是懒惰执行。正在用到类的时候,才会加载。否则不会加载到方法区
    2. 链接
      • 1.验证 - 验证类是否符合Class规范,合法性、安全性检查
      • 2.准备 - 为static 变量分配空间
      • 3.解析 - 将常量池的符号引用解析为直接引用
      • 4.final 静态变量赋值
    3. 初始化
      • 1.执行静态代码块为非final 静态变量赋值
      • 2.初始化是懒惰执行的
  • 何为双亲委派
    • 所谓的双亲委派,就是指优先委派上级类加载器进行加载,如果上级类加载器
    • 1.能找到这个类,由上级加载,加载后该类也对下级加载器可见
    • 2.找不到这个类,则下级加载器才有资格执行加载

一道错误的面试题解答

能不能自己写一个类叫 java.lan.System?

  • 错误的回答
    答:通常是不可以的,但可以采取另类方法达到这个需求。
    解释:为了不让我们写System类,类加载采用委托机制,这样可以保证爸爸们优先,爸爸们能找到的类,儿子就没有机会加载。而System类是Bootstrap加载器加载的,就算自己重写,也总是使用java系统提供的System,自己写的System类根本就没有机会得到加载。
    但是,我们可以自己定义一个类加载器来达到这个目的,为了避免双亲委派机制,这个类加载器也必须是特殊的。由于系统自带的三个类加载器都加载特定目录下的类,如果我们自己的类加载器放在一个特殊的目录,那么系统给的加载器就无法加载,也就是最终还是由我们自己的加载器加载。
  • 错在哪里了?
    自己编写类加载器就能加载一个假冒的java.lang.System吗?
    不行
    • 1.假设你自己的类加载器用双亲委派,那么优先由启动类加载器加载真正的java.lang.System,自然不会加载假冒的
    • 2.假设你自己的类加载器不用双亲委派,那么你的类加载器加载假冒的java.lang.System时,它需要先加载父类java.lang.Object,而你没有用委派,找不到java.lang.Object所以加载会失败
    • 3.以上仅仅是假设。实际操作你就会发现自定义类加载器加载以java.大头的类时,会抛出安全异常,在jdk9以上版本这些特殊包名都与模块进行了绑定,更连编译都过不去
  • 双亲委派的目的是什么?
    • 1.上级加载器加载的类对下级共享(反之不行),即能让你的类能依赖到jdk提供的核心类
    • 2.让类的加载有优先次序,保证核心类优先加载

对象的引用类型分为哪几种

  • 1.强引用
    • 1.普通变量赋值即为强引用,如 A a = new A();
    • 2.通过GC Root 的引用链,如果强引用找不到该对象,该对象才会被回收
  • 2.软引用(SoftReference)
    • 1.例如:SofReference a = new SoftReference(new A());
    • 2.如果仅有软引用该对象时,首次垃圾回收不会回收该对象,如果内存仍不足,再次回收时才会释放对象
    • 3.软引用自身需要配合引用队列来释放
    • 4.典型例子是反射数据
  • 3.弱引用(WeakReference)
    • 1.例如: WeakReference a = new WeakReference(new A());
    • 2.如果仅有弱引用引用了该对象时,只要发生垃圾回收,就会释放该对象
    • 3.弱引用自身需要配合引用队列来释放
    • 4.典型例子是ThreadLocalMap中的Entry对象
  • 4.虚引用(PhantomReference)
    • 1.例如:PhantomReference a = new PhantomReference(new A())
    • 2.必须配合引用队列一起使用,当虚引用引用的对象被回收时,会将虚引用对象入队,由Reference Handler 线程释放其关联的外部资源
    • 3.典型例子是Cleaner释放DirectByteBuffer占用的直接内存

finalize的理解?

  • 一般的回答:它是Object中的一个方法,子类重写它,垃圾回收此方法会被调用,可以在其中进行一些资源释放和清理工作
  • 较为优秀的方法:将资源释放和清理放在finalize方法中是非常不好的,非常影响性能,严重时甚至会引起oom,从java9开始就被标注为@Deprecated,不建议被使用
  • 但是,为什么?性能不好
    • 1.非常不好
      • 1.FinalizerThread是守护线程,代码很有可能没有来得及执行完,线程就结束了,造成资源没有正确释放
      • 2.异常被吞掉了,这个就太糟了,你甚至不能判断 有没有在释放资源时发生错误
    • 2.影响性能
      • 1.重写了finalize方法的对象在第一次被GC的时候,并不能及时释放它占用的内存,因为要等着FinalizerThread调用完finalize,把它从第一个unfinalized队列移除后,第二次gc时才能真正释放内存
      • 2.可以想象gc本就因为内存不足引起,finalize调用又很慢(两个队列的移除操作,都是串行执行的,用来释放连接类的资源也应该不快),不能及时释放内存,对象释放不及时就会逐渐移入老年代,老年代垃圾累积过多就会容易full gc,full gc 后释放速度如果仍跟不上创建新对象的速度,就会OOM
    • 3.质疑
      • 1.有的文章提到【Finalizer线程会和我们的主线程进行竞争,不过由于它的优先级较低,获取到的CPU时间较少,因此它永远也赶不上主线程的步伐】这个显然是错误的,FinalizerThread的优先级较普通线程更高,赶不上步伐的原因应该是finalize执行慢等原因导致的

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

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

相关文章

mars3d将当前视⻆指向北⽅且加载建筑物白膜

通过 setView⽅法实现&#xff0c;可以设置heading参数控制相对旋转⻆度map.scene.camera.setView({ orientation: { heading: 0, } }) 相关示例&#xff1a;1.http://mars3d.cn/editor-vue.html?idmap/options/scene2.功能示例(Vue版) | Mars3D三维可视化平台 | 火星科技// *…

ESP32S3 SPI发送间隔频率 驱动ADS8326

ESP32S3 SPI发送间隔频率驱动ADS8326esp32s3 spi例程 代码测试用寄存器方式实现spi发送寄存器描述驱动ADS8326 ads8326驱动时序 首先CS信号拉低&#xff0c;然后clk发送6个时钟&#xff0c;ads8326开始启动转换。 最后clk发送16个时钟&#xff0c;就会读取到两个字节的数据&a…

Spring扫描逻辑原码解析(带图好理解)

先上流程图 再上类图 再上代码 public static void main(String[] args) {XsmApplicationContext applicationContextnew XsmApplicationContext(AppConfig.class);System.out.println(applicationContext.getBean("userService"));System.out.println(applicationCo…

Laravel框架学习笔记——Laravel环境配置及安装(Ubuntu20.04为例)

目录引言1、安装Nginx2、安装PHP3、安装Composer4、搭建Laravel框架项目5、修改Nginx映射6、安装MySQL引言 好久没写博客了&#xff0c;因为个人需要&#xff0c; 所以要涉及到Laravel框架的学习&#xff0c;所以会出一系列的关于PHP的Laravel框架学习笔记&#xff0c;希望能够…

【平台数仓设计——2023】

平台数仓设计——2023前言一、选取大数据平台1、CDH大数据平台2、HDP大数据平台3、CDP大数据平台4、各种云数据中台二、选取调度平台1、DolphinScheduler(海豚调度)2、AzKaban3、Oozie4、Airflow5、corntab命令三、选取数仓设计方案1、离线数仓2、实时数仓3、离线实时一体化数仓…

尚医通 (二十二)预约下单

目录一、预约下单功能(一)1、需求2、搭建订单模块3、封装Feign调用获取就诊人接口4、封装Feign调用获取排班下单信息接口二、预约下单功能(二)1、实现生成订单接口三、预约下单功能(三)四、预约下单功能(四)1、生成订单后处理逻辑-封装短信接口2、生成订单后处理逻辑-更新排班数…

cracklib与libpwquality 评估密码的安全性

一、cracklib 检测密码强弱linux中采用pam pam_cracklib module来实现对密码强度的检测&#xff0c;可以通过配置让linux系统自动检测用户的密码是否为弱密码。yuminstall cracklib # centos apt-get install libcrack2 # ubuntu # 如果需要依赖此库做开发的话需要安装这个 y…

墨者——内部文件上传系统漏洞分析溯源 内部文件上传系统漏洞分析溯源

墨者——内部文件上传系统漏洞分析溯源 内部文件上传系统漏洞分析溯源 1.选择合适的文件上传 2.可以看到为*.asp文件 3.可以推测出此站点为IIS 4.上传shell.asp试试 5.上传报错&#xff0c;将其改名为shell.asp.txt上传&#xff0c;发现上传成功 6.有个问题就是服务器将我们所…

Node 10.0.8.6:9003 is unknown to cluster

解决方案解决方案一解决方案一 ① 概念介绍 公网ip&#xff1a;就是任意两台连接了互联网的电脑可以互相ping ip,能够通的ip 内网ip&#xff1a;只是在内网中使用无法与外网连接的ip ②问题背景 在腾讯云上搭建的一个redis集群&#xff0c;集群启动后 可以看到启动节点…

腾讯企微、泛微、契约锁举办的这场大会,超1000人共商数字化转型

全程数字化运营平台体验大会 2月23日下午&#xff0c;腾讯企业微信、泛微、契约锁在上海联合举办了全程数字化运营平台体验大会&#xff0c;旨在推动政企客户的数字化转型。 活动以“智能、协同、高效”为主题&#xff0c;吸引了上千位政府及企事单位的信息化负责人参与。 在…

Tapdata 和 Databend 数仓数据同步实战

作者&#xff1a;韩山杰https://github.com/hantmacDatabend Cloud 研发工程师基础架构在云计算时代也发生着翻天地覆的变化&#xff0c;对于业务的支持变成了如何能利用好云资源实现降本增效&#xff0c;同时更好的支撑业务也成为新时代技术人员的挑战。 本篇文章通过&#xf…

含泪推荐5款小体积,超实用的工具

大家好&#xff0c;我又来啦&#xff0c;今天给大家带来的5款软件&#xff0c;共同特点都是体积小、无广告、超实用&#xff0c;大家观看完可以自行搜索下载哦。 1.文字自动验证工具——LanguageTool LanguageTool是一款文字自动验证工具&#xff0c;不仅支持中英文&#xff…

如何将虚拟机ubuntu设置网路连接为桥接模式

当将虚拟机的网络适配器设置为NAT模式时&#xff0c;一切正常&#xff0c;可以ping通所有ip, 但是当设置为桥接模式时&#xff0c;ping命令会提示ubuntu connect: Network is unreachable 这是因为桥接模式没有设置正确&#xff0c;通过下面的步骤可以将桥接模式配置正确。 1…

iOS 生命周期 (最新最完整)

要知道APP的生命周期&#xff0c;首先要了解一下生命周期的5种状态&#xff0c;结合状态理解生命周期的使用。 一、应用的状态 应用的状态包括&#xff1a; 1.1 未运行&#xff08;Not running&#xff09; 程序没启动 1.2 未激活&#xff08;Inactive&#xff09; 程序在…

尚医通 (二十一)预约挂号功能

目录一、预约挂号详情1、需求2、预约挂号详情接口3、预约挂号详情前端二、预约确认1、需求2、预约确认接口3、预约确认前端一、预约挂号详情 1、需求 接口分析 &#xff08;1&#xff09;根据预约周期&#xff0c;展示可预约日期数据&#xff0c;按分页展示 &#xff08;2&…

JAVA设计模式之工厂模式讲解

目录 前言 开始表演 前言 Java中使用工厂模式的主要原因是为了实现代码的灵活性和可维护性。工厂模式是一种创建型设计模式&#xff0c;它提供了一种将对象的创建和使用进行分离的方式。具体来说&#xff0c;工厂模式可以将对象的创建过程封装在一个独立的工厂类中&#xff…

自动微分记录

计算图(数据流图):AI系统化问题 - 计算图的提出 计算图和自动微分 单算子切分、图的切分和调度 前端->统一表示->优化层->运行时态->底层库 语言 计算网络模型中间表示 计算图 自动微分 计算图优化 内存管理、计算图调度和执行 内核代码优化与编译 多硬件支持…

ip-guard如何在控制台上判断策略是否下发成功?

方法1.看控制台策略设置是否带*号,一般带*,然后刷新控制台依旧带*,说明策略没下发。可以点击刷新按钮进行刷新。 方法2.运行cmd,将控制台程序拖入命令行中,加参数-ad,回车运行。 然后,选中指定客户端,在维护-命令行,输入policy,

骨传导耳机是怎么发声的,骨传导耳机值得入手嘛

现在市面上除了我们平时比较常见的有线耳机、头戴耳机、真无线耳机&#xff0c;近两年还涌现出了一种有着黑科技之称的特别耳机——骨传导耳机&#xff0c;并且因其在运动场景下的优势过于明显而得到了众多运动爱好者的大力追捧。那么今天我们就来聊聊这款所谓的黑科技骨传导耳…

webform如何升级mvc

1.创建项目 给项目起名字然后指定存储位置 选择asp.net 空项目 2.新建model namespace WebFormToMvc {/// <summary>/// 用户模型/// </summary>public class UserModel{/// <summary>/// id/// </summary>public int Id { get; set; }/// <sum…