JVM相关知识
JVM
- 类加载过程
- 类什么时候被加载
- 什么情况下会发生栈内存溢出
- JVM内存模型
- 常量池
- 回收方法区
- 垃圾回收流程
- 圾收集算法
- 分代收集理论
- 标记-清除算法
- 标记-复制算法
- 标记-整理算法
类加载过程
加载–验证–准备–解析–初始化–使用–卸载
加载:通过全类名获取类的二进制流,然后解析成静态数据结构存储在方法区,并在堆中生成一个便于用户调用的java.lang.Class类型的对象
验证:验证class文件的格式是够正确 。不会威胁到JVM安全
准备:为类的静态变量分配内存,并初始化值
解析:将类,接口、字段和方法符号引用转为直接引用;假设一个类A被编译成class文件,并且A引用了B,在编译阶段,A就需要一个字符串去记录B的地址,字符串就叫符号引用,在运行时,A类被加载,但是B未被加载,那么将加载B,此时A的符号引用会被替换成B的实际地址
初始化:初始化就是类加载的最后一个阶段了。准备阶段变量可能已经被赋过初值了,初始化的时候会根据程序代码的要求来对类里的一些变量和数据进行操作。也可以说就是在调用<clinit()>方法
类什么时候被加载
- 创建类的实例,也就是new一个对象
- 访问某个类或接口的静态变量,或者对该静态变量赋值
- (注:类中的static final 修饰的基本类型及String类型成员变量,被访问是不会触发类加载的;静态内部类也是被访问不会触发类加载)
- 调用类的静态方法
- 反射
- 初始化一个类的子类(会首先初始化子类的父类)
- JVM启动时标明的启动类,即文件名和类名相同的那个类
手动触发类加载 class.forname
如果两个线程同时class.forname,只会加载一次,第二个会阻塞,第二个会,他也就跟着返回的了
什么情况下会发生栈内存溢出
当线程请求的栈深度超过了虚拟机允许的最大深度时,会抛出StackOverFlowError异常,方法递归调用可能会出现该问题;调整参数-xss去调整jvm栈的大小
JVM内存模型
思路: 给面试官画一下JVM内存模型图,并描述每个模块的定义,作用,以及可能会存在的问题,如栈溢出等。
Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。
这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。
创建对象会放在堆里面.
信息、类信息开始进入方法区,程序执行进入栈当中,在栈当中有new这些操作,引出堆的调用,栈的运行由程序计数器配合计时进行实现,需要操作系统执行的话就需要依赖本地方法栈翻译成计算机可以执行的语言,来进行操作。
线程共享:
- 堆—存实例化的对象
- 方法区—主要存放的是class(类信息)
线程独享:
- 程序计数器—存下一行要执行的行号
- 虚拟机栈—存栈帧(局部变量表)
- 本地方法栈—调用本地方法的时候存的数据
1、程序计数器:
- 线程私有,线程间会切换,为了让线程切换回来指定到准确的位置,需要有独立的程序计数器,记录这个线程执行到了哪里,下一行改执行哪个指令。
- 程序计算器是唯一不会发生内存溢出的地方。如果正在执行的是Native 方法,由于不是JVM执行,则这个计数器值为空。
2、Java虚拟机栈:
-
线程私有,每个方法执行的时候,在虚拟机里面同步创建一个栈帧,存储局部变量表、操作数栈、动态连接、方法出口等信息。方法从被调用到执行完毕就对应着一个栈帧。
-
【编译的时候就能知道方法需要多少位空间,如果是字符串型(不确定位数),会存一个指向,这个指向占固定位数】
3、本地方法栈:
- 和上面类似(java底层封装了c语言,操作系统不认识,需要翻译成本地的c语言)【将自己本身封装的方法,重新翻译成操作系统可识别的方法(C和汇编),本地方法栈和操作系统进行沟通。】
- 本地方法栈是操作系统本地的方法
- 本地方法栈是线程私有的,java虚拟机调用本地方法时,需要给本地方法提供的内存空间。存的是native信息,当一个JVM创建的线程调用native方法后,jvm不会在虚拟机栈中为该线程创建栈帧,而是简单的动态链接直接调用该方法。
- 堆中的方法能不能被gc回收(可以)
- 方法区中的东西可以被gc回收嘛(可以,类型卸载)
- 栈中的东西不需要回收,方法执行完栈就销毁了。
4、Java堆:
- **线程共享,**存对象实例(所有的对象实例以及数组都应当在堆上分配)(但是其中仍然有线程私有的区域,称为TLAB,它可以提高对象分配的效率)
- Java堆是垃圾收集器管理的内存区域
- 从分配内存的角度看,所有线程共享的Java堆中可以划分出多个线程私有的分配缓冲区
- 将Java堆细分的目的只是为了更好地回收内存,或者更快地分配内存
- 对于**基本数据类型对象,**在方法体内声明时,会直接分配在栈中,其它情况都会分配在堆中。
- 对于**普通对象来说,**JVM 会首先在堆上创建对象,然后在其他地方使用它的引用。
5、方法区:
- 线程共享,存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等。
- 在JDK 6的时候HotSpot开发团队就有放弃永久代,逐步改为采用本地内存来实现方法区的计划。
- 到了JDK 7的HotSpot,已经把原本放在永久代的字符串常量池、静态变量等移出。
- JDK 8,终于完全废弃了永久代的概念
6、运行时常量池:
- 运行时常量池是方法区的一部分
7、直接内存:
- 物理上内存条
- JVM占的内存是我们自己写的C和汇编所占据的内存,不属于JVM数据区一部分,属于本机运行内存。执行JVM的时候还需要调用操作系统内核
- 提供的方法,操作系统也需要消耗内存,这时就用到了直接内存,一般程序都消耗直接内存
- 知识扩展:操作系统调取内核提供的方法,内核连接驱动,驱动硬件只识别汇编语言,硬件中加了存储功能有一套翻译,支持C语言的识别
常量池
JVM常量池主要分为Class文件常量池、运行时常量池,全局字符串常量池,以及基本类型包装类
对象常量池。
●Class文件常量池。在java代码的编译期间, 我们编写的java文件就被编译为.class文件格式的二进制数据存放在磁盘中,其中就包括class文件常量池。
●**运行时常量池:**方法区内
字符串常量池:在HotSpot VM中,它是一个叫做StringTable的全局表。string”或通常所说的"进入了字符串常量池的字符串”。存放在堆中
●基本类型包装类对象常量池: 这些类是Byte, Short,Integer,Long,Character,Boolean,。另外上面这5种整型的包装类也只是在对应值小于等于
127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象。
回收方法区
方法区又称元空间或者永久代(HotSpot虚拟机中老版本的叫法)
主要回收内容:
-
废弃的常量
已经没有任何字符串对象引用常量池中的“java”常量,且虚拟机中也没有其他地方引用这个字面量,如果在这时发生内存回收,而且垃圾收集器判断确有必要的话,这个“java”常量就将会被系统清理出常量池
-
不再使用的类
判定一个类型是否属于“不再被使用的类”的三个条件:
1.该类所有的实例都已经被回收,也就是Java堆中不存在该类及其任何派生子类的实例。
2.加载该类的类加载器已经被回收
3.该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
垃圾回收流程
当一个对象被实例化后,首先先尝试存在eden区,若Eden区存不下,将触发一次minor GC,若空间不够,则看存活区的空间是否够,要是够的话,将Eden区的存活时间长的对象放到存活区,将新创建的对象分配到Eden区,要是不够的话,看老年代的空间是否够,要是够的话,将存活区的存活时间比较长的对象存到老年代,然后将Eden区的存活时间比较长的存到存活区,将新创建的分配搭到Eden区。若空间仍不够,触发一次full GC,重复操作,若最后空间仍不足,抛出异常。
圾收集算法
垃圾收集灵魂三问
- 判定哪些对象是垃圾
- 什么时候回收
- 怎么进行回收
分代收集理论
当前的垃圾收集器,大多数都遵循了“分代收集”的理论进行设计分代收集理论,实质是一套符合大多数程序运行实际情况的经验法则,建立在两个分代假说之上:
1)弱分代假说:绝大多数对象都是朝生夕灭的。(不用分代,全部死亡)
2)强分代假说:熬过越多次垃圾收集过程的对象就越难以消亡。(活时间越长的越难死)
上面两个假说奠定了一个原则:收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。
一般把Java堆划分为新生代和老年代。
在新生代中,每次垃圾收集时都发现有大批对象死去,而每次回收后存活的少量对象,将会逐步晋升到老年代中存放。
一个问题:想将新生代的对象回收,但是这个对象可能是老年代的对象指向(引用)的它,为了找出该区域中的存活对象,不得不在固定的GC Roots之外,再额外遍历整个老年代中所有对象来确保可达性分析结果的正确性,反之也要把新生代全部遍历一遍。
—>会产生很大的性能负担,因此产生了跨代引用假说
3)跨代引用假说:跨代引用相对于同代引用来说仅占极少数。
- 依据这条假说,我们就不应再为了少量的跨代引用去扫描整个老年代,也不必浪费空间专门记录 每一个对象是否存在及存在哪些跨代引用;
- 只需在新生代上建立一个全局的数据结构(该结构被称 为“记忆集”),这个结构把老年代划分成若干小块,标识出老年代的哪一块内存会 存在跨代引用。
- 此后当发生Minor GC时,只有包含了跨代引用的小块内存里的对象才会被加入到GC Roots进行扫描。
统一定义:
-
部分收集:指目标不是完整收集整个Java堆的垃圾收集,其中又分为:
-
- 新生代收集:指目标只是新生代的垃圾收集。
- 老年代收集:指目标只是老年代的垃圾收集。目前只有CMS收集器会有单独收集老年代的行为。
- 混合收集:指目标是收集整个新生代以及部分老年代的垃圾收集。目前只有G1收集器会有这种行为。
-
整堆收集:收集整个Java堆和方法区的垃圾收集。
标记-清除算法
标记出哪些需要回收或哪些不需要回收,按照标记进行回收。(这是比较基础的算法,其他的垃圾回收算法是以它为基础改进的)
标记-清除算法缺点:
- 1,是执行效率不稳定
- 2,是内存空间的碎片化问题
标记-复制算法
为了解决标记-清除算法面对大量可回收对象时执行效率低的问题,提出了一种称为“半区复制”的垃圾收集算法—将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。两边循环往复。
标记-复制算法优点:
- 实现简单,运行高效;
标记-复制算法缺点:
- 可用内存缩小为了原来的一半;
- 存活的对象比较多的时候,来回复制对象导致效率很低
标记-复制算法的优化:
Appel式回收—》
Appel式回收的具体做法是把新生代分为一块较大的Eden空间和两块较小的 Survivor空间,每次分配内存,先占用Eden空间,垃圾收集的时候,Eden存活的对象放入到Survivor1当中,清理掉Eden中的对象,Survivor1当中存活的放入到Survivor2当中,清理掉Survivor1当中的对象,Survivor2满了之后,将存活的放入到Eden中,清除Survivor2中所有的对象,永远Eden区域优先存储对象。以此类推,两块满了之后,回收的进入另外一块。
进一步优化——》
如果Eden区域存活下来的对象比较多,那么会出现两个Survived区域装不下的情况,所以需要依赖其他内存区域(实 际上大多就是老年代)进行分配担保。这些对象将通过分配担保机制直 接进入老年代
标记-复制算法缺点:在对象存活率较高时就要进行较多的复制操作,效率将会降低;如果 不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存 活的极端情况。—>老年代里面不能用这样的算法
【空间分配担保:新生代与老年代的占比一般是1:2;在新生代中,假如Eden区域30%的数据存活了下来,这样两个Survivor区域放不下这30%的对象,就将这三成数据直接放入老年代,叫做空间分配担保】
标记-整理算法
标记过程一样,后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。
标记整理算法是需要移动对象的,移动对象是相对来说比较消耗时间的。
相关文章:

JVM相关知识
JVM类加载过程类什么时候被加载什么情况下会发生栈内存溢出JVM内存模型常量池回收方法区垃圾回收流程圾收集算法分代收集理论标记-清除算法标记-复制算法标记-整理算法类加载过程 加载–验证–准备–解析–初始化–使用–卸载 加载:通过全类名获取类的二进制流…...

【LeetCode】剑指 Offer(21)
目录 题目:剑指 Offer 39. 数组中出现次数超过一半的数字 - 力扣(Leetcode) 题目的接口: 解题思路: 代码: 过啦!!! 题目:剑指 Offer 40. 最小的k个数 -…...

线性求解器Ax=b的验证
文章目录前言Matrix MarketMatlab IORead dataWrite data测试C IORead and write dataDownload MatrixIO 代码下载参考网址前言 一般情况集成了一个线性求解器(Axb),我们需要验证其性能和精度,这时需要大量数据来做验证ÿ…...

java 事件处理机制 观察者模式
事件处理机制有三个要素事件、事件源、事件监听与java的对应关系如下事件事件源事件监听javaclassjava.util.EventObjectjava.util.EventObject 的 source 属性interfacejava.util.EventListener观察者模式又被称为发布-订阅(Publish/Subscribe)模式&…...

使用 HTML5 轻松验证表单插件
下载:https://download.csdn.net/download/mo3408/87559594 效果图: 当您通过表单从人们那里收集信息时,必须应用某种验证。如果不这样做,可能会导致客户流失、数据库中的垃圾数据甚至网站的安全漏洞。从历史上看,构建表单验证一直很痛苦。在服务器端,全栈框架会为您处理…...

【Error: ImagePullBackOff】Kubernetes中Nginx服务启动失败排查流程
❌pod节点启动失败,nginx服务无法正常访问,服务状态显示为ImagePullBackOff。 [rootm1 ~]# kubectl get pods NAME READY STATUS RESTARTS AGE nginx-f89759699-cgjgp 0/1 ImagePullBackOff 0 103…...

九龙证券|直逼1.5万亿!A股融资余额创年内新高,青睐这些行业和个股
2023年以来,A股商场震动重复,商场走势整体先扬后抑,各路资金看法纷歧,但数据显现,融资客在此期间整体持续净买入,未受到商场动摇的明显冲击,融资余额日前已迫临1.5万亿元,创出年内新…...

【JavaScript】36_正则表达式
正则表达式 正则表达式 正则表达式用来定义一个规则通过这个规则计算机可以检查一个字符串是否符合规则 或者将字符串中符合规则的内容提取出来 正则表达式也是JS中的一个对象, 所以要使用正则表达式,需要先创建正则表达式的对象 new RegExp() 可以…...

参考 | 辨别真假笔记本三星内存条 (ddr4)
参考 | 辨别真假笔记本三星内存条 (ddr4) 文章目录参考 | 辨别真假笔记本三星内存条 (ddr4)1. 三星内存条标签纸上编码的含义2. 三星内存颗粒上编码的含义3. 辨别内容参考1. 三星内存条标签纸上编码的含义 内存条贴张上面有两串值得注意的编码, 其中编码的具体意义参考三星官方…...

JavaScript Math(算数)对象
Math(算数)对象的作用是:执行常见的算数任务。在线实例round()如何使用 round()。random()如何使用 random() 来返回 0 到 1 之间的随机数。max()如何使用 max() 来返回两个给定的数中的较大的数。(在 ECMASCript v3 之前…...

MyBatis里面用了多少种设计模式?
在MyBatis的两万多行的框架源码中,使用了大量的设计模式对工程架构中的复杂场景进行解耦,这些设计模式的巧妙使用是整个框架的精华。经过整理,大概有以下设计模式,如图1所示。图101类型:创建型模式▊ 工厂模式SqlSessi…...

第三十二周精华分享(2023.02.27-2023.03.06)
本帖是知识星球各类问答以及文章精华沉淀区,而知识星球相关资源沉淀则在置顶帖的「资源沉淀」中。 学计算机的都应该知道有个局部性原理,其实局部性原理在很多场合都适用,比如80%的圈友的痛点或者疑惑其实都集中在一些固定的方面或者问题上&…...

数学建模资料整理
数学建模中有三类团队: 第一类:拿到题目,讨论,然后建模手开始建模,编程手开始处理数据,写作手开始写作。 第二类:拿到题目,团内大佬,开始建模,然后编程&#…...

设计模式---抽象工厂模式
目录 1 介绍 2 优缺点 3 实现 1 介绍 抽象工厂模式(Abstract Factory Pattern) 是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在抽象工厂模式中,接口是负…...

Java Web 实战 07 - 多线程基础之单例模式
大家好 , 这篇文章给大家带来的是单例模式 , 单例模式中分为懒汉模式和饿汉模式 , 懒汉模式是需要用的到的时候才去创建实例 , 而饿汉模式是程序一启动就立刻创建实例 , 在这其中还有很多其他问题需要我们去研究 推荐大家跳转到这里 , 观看效果更加 上一篇文章的链接我也贴在这…...

uniapp上实现左右关联滚动
先看效果: 代码: <template><view class"container"><!-- 左侧fixed导航区域 --><view class"left"><viewv-for"item in leftList":key"item.id"class"left_item":class…...

Docker Remote API未授权访问
目录Docker简述Docker 2375端口安全风险Docker命令连接利用声明:本文仅供学习参考,其中涉及的一切资源均来源于网络,请勿用于任何非法行为,否则您将自行承担相应后果,本人不承担任何法律及连带责任。Docker简述 Docke…...

【蓝桥杯】第十四届蓝桥杯模拟赛(第三期)C++ (弱go的记录,有问题的话求指点)
博主是菜鸡啦,代码仅供参考,只确定能过样例,嘻嘻~第一题,填空题问题描述请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 …...

算法24:LeetCode_并查集相关算法
目录 题目一:力扣547题,求省份数量 题目二:岛屿数量 题目三:岛屿数量拓展 什么是并查集,举个简单的例子。学生考试通常会以60分为及格分数,我们将60分及以上的人归类为及格学生,而60分以下归…...

TypeScript核心知识点
TypeScript 核心 类型注解 知道:TypeScript 类型注解 示例代码: // 约定变量 age 的类型为 number 类型 let age: number 18 age 19: number 就是类型注解,它为变量提供类型约束。约定了什么类型,就只能给该变量赋值什么类型的…...

基于“遥感+”融合技术在碳储量、碳收支、碳循环等多领域监测与模拟实践
以全球变暖为主要特征的气候变化已成为全球性环境问题,对全球可持续发展带来严峻挑战。2015年多国在《巴黎协定》上明确提出缔约方应尽快实现碳达峰和碳中和目标。2019年第49届 IPCC全会明确增加了基于卫星遥感的排放清单校验方法。随着碳中和目标以及全球碳盘点的现…...

外卖点餐系统小程序 PHP+UniAPP
一、介绍 本项目是给某大学餐厅开发的外面点餐系统,该项目针对校内的学生,配送由学校的学生负责配送。因此,该项目不同于互联网的外卖点餐系统。 该系统支持属于 Saas 系统,由平台端、商家端、用户端、以及配送端组成。 其中&a…...

vuex3的介绍与state、actions和mutations的使用
一、定义官网:Vuex 是什么? | Vuex (vuejs.org)Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。二、安装cdn<script src"/path/…...

windows 自带端口转发
使用Portproxy模式下的Netsh命令即能实现Windows系统中的端口转发,转发命令如下: netsh interface portproxy add v4tov4 listenaddress[localaddress] listenport[localport] connectaddress[destaddress]listenaddress – 等待连接的本地ip地址 listenport – 本…...

【算法】算法基础入门详解:轻松理解和运用基础算法
😀大家好,我是白晨,一个不是很能熬夜😫,但是也想日更的人✈。如果喜欢这篇文章,点个赞👍,关注一下👀白晨吧!你的支持就是我最大的动力!Ǵ…...

2.9.1 Packet Tracer - Basic Switch and End Device Configuration(作业)
Packet Tracer - 交换机和终端设备的基本 配置地址分配表目标使用命令行界面 (CLI),在两台思科互联网络 操作系统 (IOS) 交换机上配置主机名和 IP 地址。使用思科 IOS 命令指定或限制对设备 配置的访问。使用 IOS 命令来保存当前的运行配置。配置两台主机设备的 IP …...

AtCoder Beginner Contest 216(F)
F - Max Sum Counting 链接: F - Max Sum Counting 题意 两个 大小为 nnn 的序列 aiaiai 和 bibibi,任意选取一些下标 iii,求 max(ai)>∑bi\max(ai) > \sum{bi}max(ai)>∑bi的方案数。 解析 首先考虑状态 一是和,…...

每天学一点之Stream流相关操作
StreamAPI 一、Stream特点 Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,负责存储数据,Stream流讲的是计算,负责处理数据!” 注意: ①Str…...

MatCap模拟光照效果实现
大家好,我是阿赵 之前介绍过各种光照模型的实现方法。那些光照模型的实现虽然有算法上的不同,但基本上都是灯光方向和法线方向的计算得出的明暗结果。 下面介绍一种叫做MatCap的模拟光照效果,这种方式计算非常简单,脱离灯光的计算…...

二十一、PG管理
一、 PG异常状态说明 1、 PG状态介绍 可以通过ceph pg stat命令查看PG当前状态,健康状态为“active clean” [rootrbd01 ~]# ceph pg stat 192 pgs: 192 activeclean; 1.3 KiB data, 64 MiB used, 114 GiB / 120 GiB avail; 85 B/s rd, 0 op/s2、pg常见状态 状…...