面试集中营—JVM篇

一、JVM内存模型

        线程独占:栈,本地方法栈,程序计数器;

        线程共享:堆,方法区

        虚拟机栈:线程私有的,线程执行方法是会创建一个栈阵,用来存储局部变量表,操作栈,动态链接,方法出口等信息.调用方法时执行入栈,方法返回式执行出栈;

        本地方法栈:与虚拟机栈类似,也是用来保存执行方法的信息.执行Java方法是使用栈,执行Native方法时使用本地方法栈;

        程序计数器:保存着当前线程执行的字节码位置,每个线程工作时都有独立的计数器,只为执行Java方法服务,执行Native方法时,程序计数器为空;

        堆:内存管理最大的一块,对被线程共享,目的是存放对象的实例,几乎所有的对象实例都会放在堆中;

        方法区:称非堆区,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器优化后的代码等数据.1.7的永久栈和1.8的元空间都是方法区的一种实现;

        除此以外,还有一块儿地方叫做堆外内存:Direct ByteBuffers

二、类加载与卸载

类加载的过程

        三步走:加载-链接-初始化;

        五步走:加载-验证-准备-分析-初始化

        不管是几步走,我们可以这么理解,我写了一段加密程序,然后我给了你一个解密程序。现在我把加密程序给你,为了能够把我的加密程序变成你能够使用的程序(比如a+b=c),那么第一步应该是把加密程序先下载并打开(加载)— 检查一下这个加密程序是否符合解密规范且不会对解密程序造成危害(验证)— 把加密程序变成可执行文件(准备、分析、初始化)

  • 加载通过类的完全限定名,查找此类字节码文件,利用字节码文件创建Class对象.
  • 验证确保Class文件符合当前虚拟机的要求,不会危害到虚拟机自身安全.
  • 准备进行内存分配,为static修饰的类变量分配内存,并设置初始值(0null).不包含final修饰的静态变量,因为final变量在编译时分配.
  • 解析将常量池中的符号引用替换为直接引用的过程.直接引用为直接指向目标的指针或者相对偏移量等.
  • 初始化主要完成静态块执行以及静态变量的赋值.先初始化父类,再初始化当前类.只有对类主动使用时才会初始化.

 加载机制-双亲委派机制

        这里的双亲不是真的有两个类加载器,一个父亲一个母亲,而是指parent,parent就是父母的意思,翻译过来叫双亲;

        即加载器加载类时先把请求委托给自己的父类加载器执行,直到顶层的启动类加载器。父类加载器能够完成加载则成功返回,不能则子类加载器才自己尝试加载。换句话说遇到class加载先叫爸爸,爸爸找自己的爸爸,自己的爹搞不定了自己再尝试加载。

        优点就是避免类的重复加载、避免Java的核心API被篡改,比如你写了一个String类,难道系统启动的时候要使用我们自己的写的String类来替换java.lang下的String类吗?

类加载器

        类的加载是由类加载器完成的,类加载器包括:根加载器(BootStrap)、扩展加载器 (Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子 类)。从Java2JDK1.2)开始,类加载过程采取了父亲委托机制(PDM)。PDM更好地保证了Java平台的安全性,在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且仅有一个父类加载器。类的加载首先请求父类加载器加载,父类加载器无能为力时才由其子类加载器自行加载。JVM不会向Java程序提供对Bootstrap的引用。

        Bootstrap:一般用本地代码实现,负责加载JVM基础核心类库(rt.jar);

        Extension:从java.ext.dirs系统属性所指定的目录中加载类库,它的父加载器是Bootstrap

        System:又叫应用类加载器(Application),其父类是Extension。它是应用最广泛的类加载器。它从环境变量classpath或者系统属性java.class.path所指定的目录中记载类,是用户自定义加载器的默认父加载器;

三、对象分配规则

        这里主要讲述对象在堆内存中的生命历程。

        1、对象优先分配在Eden区,当Eden区没有足够的空间时,会触发一次minorGC;

        2、大对象直接进入老年代(大对象是指需要大量连续内存空间的对象)。这样做的目的是避 免在Eden区和两个Survivor区之间发生大量的内存拷贝

        3、长期存活的对象进入老年代,老年代就是要上了一定年纪,每次minorGC,还存活的对象年龄加1,年龄到达某个值(默认好像是15)就会进入老年代,表示这个对象应该会长期活在内存中,把Eden区的空间留给新的对象;

        4、动态判断对象的年龄。如果Survivor区中相同年龄的所有对象大小的总和大于Survivor 空间的一半,年龄大于或等于该年龄的对象可以直接进入老年代;

        5、空间分配担保:每次进行MinorGC时,JVM会计算Survivor区移至老年区的对象的平均大小,如果这个值大于老年区的剩余值大小则进行一次FullGC;老年代无法分配这么多的内存可能会造成内存溢出;

四、Java对象的创建过程

         1、当遇到一条新建对象的指令时,先要检查能否在常量池中找到定义这个类的符号引用,如果存在引用,就加载这个类;

         2、为对象分配内存空间:

        指针碰撞:如果内存分配是一片连续的区域,那么只需要把空闲指针移动内存大小即可分配内存;

        空闲列表:如果内存分配是不连续的,就需要一个列表来记录哪些是空闲的; 

        TLAB:本地线程分配缓冲区(Thread Local Allocation Buffer)是Java虚拟机堆内存中的一个特殊区域,专门为线程分配对象而设计。TLAB是Eden区的一部分,每个线程在初始化时会被分配一块TLAB空间,这块空间仅供当前线程使用。线程在分配内存时,会在自己的TLAB上进行分配,这样可以避免多线程间的内存分配竞争,从而提高分配效率。

        3、将除对象头外的对象内存空间初始化为0

        4、初始化对象头信息

五、Java的对象结构

        对象由三个部分组成:对象头、实例数据、对齐填充

        对象头:由两部分组成,第一部分存储对象自身的运行时数据:哈希码、GC分代年龄、锁标识状态、线程持有的锁、偏向线程ID(一般占32/64bit)。第二部分是指针类型,指向对象的类元数据类型(即对象代表哪个类)。如果是数组对象,则对象头中还有一部分用来记录数组长度。

        实例数据:用来存储对象真正的有效信息(包括父类继承下来的和自己定义的);
        
        对齐填充:JVM 要求对象起始地址必须是 8 字节的整数倍( 8 字节对齐)

六、逃逸分析技术

        逃逸分析(EscapeAnalysis),是一种可以有效减少Java程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,JavaHotspot编译器能够分析出一个新的对象的引用的使用范围,从而决定是否要将这个对象分配到堆上。

        通俗点讲,如果一个对象的指针被多个方法或者线程引用时,那么我们就称这个对象的指针发生了逃逸。优点如下:

  • 栈上分配,可以降低垃圾收集器运行的频率;这样的好处有,一、减少内存使用,因为不用生成对象头。二、程序内存回收效率高,并且GC频率也会减少
  • 同步消除,如果发现某个对象只能从一个线程可访问,那么在这个对象上的操作可以不需要同步;

七、为什么使用元空间替换了永久栈

        先看几个概念:

        方法区: 方法区和堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据;

        永久代:在JDK1.7及以前的版本中,永久代就是方法区在Hotspots中的实现

        元空间:对于Java8HotSpots取消了永久代,取而代之的是元空间(Metaspace)。换句话说,就是方法区还是在的,只是实现变了,从永久代变为元空间了。

        那么为什么要替换呢?主要是解决方法区内存OOM的问题,方法区的内存和堆内存是一片连续的空间,默认最大值是64MB,而1.8以后的方法区放在独立的元空间中,和堆内存是不连续的,没有内存的限制,理论上系统内存剩余多大就可以用多大;

八、STW、Oopmap与安全点

        STW:Stop the world, 在进行垃圾回收的时候,当需要移动对象时为了保证对象引用更新的正确性,必须要停止所有的用户线程,等移动结束以后再放开,这就是STW;

        Oopmap:HotSpot中,有个数据结构(映射表)称为Oopmap,HotSpot会把对象内什么偏移量上是什么类型的数据计算出来,记录到OopMap。在即时编译过程中,也会在「特定的位置」生成OopMap,记录下栈上和寄存器里哪些位置是引用。 这些特定的位置就叫安全点

        安全点:Safe  Point,主要在以下三种地方

        1、循环的末尾; 

        2、方法临返回前/调用方法的call指令后;

        3、可能抛异常的位置;

        STW并不是任意时刻都可以进行,用户线程要停顿下来开始垃圾收集,必须是执行到安全点才能够暂停;

       

        

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

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

相关文章

Linux提示:mount: 未知的文件系统类型“ntfs”

mount: 未知的文件系统类型“ntfs” 在Linux系统中,如果遇到“mount: 未知的文件系统类型‘ntfs’”的错误,这通常意味着您的系统没有安装支持NTFS文件系统的软件。为了挂载NTFS文件系统,您需要安装ntfs-3g软件包。以下是如何在不同Linux发行…

05-06 周一 Shell工程目录划分和开发最佳实践

05-06 周一 Shell工程目录划分和开发最佳实践 时间版本修改人描述2024年5月6日10:34:13V0.1宋全恒新建文档2024年5月6日11:07:12V1.0宋全恒完成 简介 之前楼主曾经完成过一个shell工程的开发,记得当时项目名称叫做campus-shell,主要是用来一键完成多个模…

Web Component fancy-components

css-doodle 组件库 fancy-components 组件库使用 yarn add fancy-components使用: import { FcBubbles } from fancy-components new FcBubbles() //要用哪个就new哪个 new 这里可能会报错eslink,eslintrc.js中处理报错 module.exports {rules: {no-new: off} …

OceanBase 如何实现多层面的资源隔离

OceanBase的资源隔离涵盖了多个方面,如物理机器间的隔离、不同租户之间的隔离、同一租户内的隔离,以及针对大型查询请求的隔离等。在实际应用OceanBase的过程中,我们经常会遇到这些操作场景或产生相关需求。这篇文章针对这些内容进行了简要的…

PWN入门--栈溢出

PWN入门–栈溢出 栈概要 介于网上各种wp在栈溢出利用脚本方面浅入浅出,深入讲一下栈溢出利用时,地址如何计算,栈中垃圾数据如何填充,函数调用时 参数 在栈中的分布, 栈帧的生成,函数返回值ip在栈中的摆放…

国内如何下载TikTOK,手机刷机教程

最近很多玩家都来问怎么刷机?手机环境怎么搭建?这里给大家整理了苹果IOS刷机教程 1.iOS下载教程 : 步骤一:手机调试 苹果手机系统配置推荐:iPhone6S以上,16G。 注意:如果是选择购入二手手机…

【北京迅为】《iTOP-3588开发板源码编译手册》-第4章 Android12/Linux设备树简介

RK3588是一款低功耗、高性能的处理器,适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用,RK3588支持8K视频编解码,内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

千川投流助力直播间场观,快速增粉满足500有效粉标准,轻松开通带货权限和直播间真实流量的提升!

随着短视频带货的兴起,抖音成为了越来越多商家和创业者的首选平台。然而,最近一项新政策给广大抖音创作者带来了一定的挑战:只有拥有500有效粉的账号才能开通带货权限。为了帮助用户满足这一要求,抖音官方渠道推出了巨量千川投流服…

Python实验代码定时调起

Python代码实验调参需要等待1小时运行完成,自动将提前设置的5组参数(每组参数有8个)间隔1小时之后让Python代码再次自动依次调起运行其中的一组参数,每次跑完将实验结果写一个文件在本地存储通过邮件发送运行结果到指定QQ邮箱 im…

effective python学习笔记_pythonic思维

查py版本 import sys sys.version sys.version_info 遵循PEP8 PEP8,Python Enhancement Proposal #8 章节列了几个点,也可以看原文PEP 8 – Style Guide for Python Code | peps.python.org 导包顺序建议:先导标准库模块,再导三方模块&…

【论文阅读】Fuzz4All: Universal Fuzzing with Large Language Models

文章目录 摘要一、介绍二、Fuzz4All的方法2.1、自动提示2.1.1、自动提示算法2.1.2、自动提示的例子2.1.3、与现有自动提示技术的比较 2.2、fuzzing循环2.2.1、模糊循环算法2.2.2、Oracle 三、实验设计3.1、实现3.2、被测系统和baseline3.3、实验设置以及评估指标 四、结果分析4…

uniapp-ios支付

uniapp安卓包中的微信,支付宝逻辑放在iOS测试包中也能使用. 但询问iOS开发者后得知,有支付相关功能的app要上架苹果,必须先有苹果支付,不然苹果审核不给过.甚至没有支付逻辑,但打包时有支付相关的SDK也不行,苹果会认为你偷偷做了支付逻辑,想要绕开他. 一. 去苹果开发者后台把…

Labels and Databases for Mac:强大的标签与数据库管理工具

Labels and Databases for Mac是一款集标签制作与数据库管理于一体的强大工具,专为Mac用户打造,旨在提供高效、便捷的标签制作与数据管理体验。 这款软件拥有丰富的内置标签格式,用户可轻松创建各种标签、信封和卡片,满足个性化需…

某东抢购某台脚本——高版本

某东抢购某台脚本——高调 小白操作-学习参考 说明 这个脚本用于自动化京东的秒杀过程,特别是对于高需求商品如茅台。它展示了通过自动化工具模拟用户行为的能力,但同时也涉及到了使用自动化脚本可能违反网站使用条款的问题。使用此类脚本前应确保合…

ATFX汇市:日本央行或3万亿干预,日元升值势头显著

​ATFX汇市:4月29日,USDJPY创出历史新高160.21,随后进入快速回落阶段。五个交易日,最低价触及151.86点,相比最高价暴跌835基点,约5.21%。同期的美元指数跌幅仅为0.96%,两者跌幅严重不匹配&#…

编程语言QT、C++、C#、Matlab、SQL Server开发日志总结

目录 引言 正文 1、Qt连接SQL server数据库 2、C#使用chart绘制实时折线图,波形 3、ORACLEXE数据库 4、QT通过ODBC驱动连接Oracle数据库 5、Microsoft SQL Server 2014 安装图解 6、SQL Server 2014应用 7、C/C​​​​​​​ 8、QT…

全国33个省228189个矿产地位置分布数据,含经纬度坐标/CSV格式

全国矿产地分布(2021版) 数据来源: 全国矿产地数据库2021版 (ngac.org.cn) http://data.ngac.org.cn/mineralresource/index.html 数据获取方法:树谷资料库大全(2024年4月19日更新) 进入网站后&#xf…

记一次favicon.ico的折腾

某项目需要将前端和后台整合在一起 我也不知道为啥要整合 上面有要求就整呗 正常前端npm run build打包后 dist内会根据设置自动生成favicon.ico文件在根目录下 但由于前后端整合 需要打包后将图标放在dist下的static文件夹里 需要的效果 打包后 index.html里 <link rel&…

网络基础(1)详解

目录 1.计算机网络背景 2.网络协议 3.网络中的地址管理 1.计算机网络背景 1.1 网络发展 (1)计算机从独立模式到网络互联(多态计算机连接共享数据)再到局域网LAN(通过交换机和路由器连接)接着是广域网WAN 1.2 协议 协议就是双方的一种约定. 为什么要有协议? 因为在数据长距…

c++ cpp 在类中执行线程 进行恒定计算

在编程中&#xff0c;顺序执行是常见的模式&#xff0c;但是对cpu的利用率不是很高&#xff0c;采用线程池&#xff0c;又太麻烦了&#xff0c;原因是还得不断地把任务拆分&#xff0c;扫描返回值。 如果 初始化n个类的时候&#xff0c;传递数据自身即可异步计算&#xff0c;那…