Java 面试题(3)—— JVM

JVM的内存结构。


JVM主要结构:堆内存、栈、方法区,程序计数器,永久代)(jdk 8采用元空间替代)。
堆内存又分成年轻代和年老代。
年轻代由三部分组成,Eden、From Survivor 和 To Survivor,这三者默认分配的比例是8:1:1。
方法区主要存储类信息、常量、静态变量等数据。
栈又分为java虚拟机栈和本地方法栈,每创建一个线程对应一个java栈,
每调用一个方法就会向栈中创建并压人一个栈帧,栈帧是用来存储方法数据和部分过程结果的数据结构,
每一个方法从调用到最终返回结果的过程,就对应一个栈帧从入栈到出栈的过程。
本地方法栈主要用于native方法的调用。
程序计数器(Program Counter Register)是JVM中一块较小的内存区域,保存着当前线程执行的虚拟机字节码指令的内存地址。
所有线程共享的内存数据区:方法区,堆。而虚拟机栈,本地方法栈和程序计数器都是线程私有的。


JVM方法栈的工作过程,方法栈和本地方法栈有什么区别。


每个线程拥有自己的栈,栈包含每个方法执行的栈帧。
栈是一个后进先出(LIFO)的数据结构,因此当前执行的方法在栈的顶部。
每次方法调用时,一个新的栈帧创建并压栈到栈顶。
当方法正常返回或抛出未捕获的异常时,栈帧就会出栈。
除了栈帧的压栈和出栈,栈不能被直接操作。
所以可以在堆上分配栈帧,并且不需要连续内存。


JVM的栈中引用如何和堆中的对象产生关联。


在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,
让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。
Java的堆是一个运行时数据区,类的(对象从中分配空间。
这些对象通过new、newarray、anewarray和multianewarray等指令建立,它们不需要程序代码来显式的释放。
堆是由垃圾回收来负责的,堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,
因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。
但缺点是,由于要在运行时动态分配内存,存取速度较慢。 

栈的优势是,存取速度比堆要快,仅次于寄存器,栈数据可以共享。
但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
栈中主要存放一些基本类型的变量(, int, short, long, byte, float, double, boolean, char)和对象句柄。 

https://www.cnblogs.com/langren1992/p/4738391.html
https://www.jianshu.com/p/ac162726d7de

可以了解一下逃逸分析技术。


方法逃逸:当一个对象在方法中被定义后,因为可能被外部方法引用,比如作为调用参数被传递到其他的方法里。
线程逃逸:当一个对象在方法中被定义后,可能被外部线程访问到,比如给类变量或者在其他线程中访问的实例变量。
栈上分配:就是把没发生逃逸的对象,在栈分配空间。(一般对象分配空间是在堆)
jvm根据对象是否发生逃逸,会分配到不同(堆或栈)的存储空间。如果对象发生逃逸,那会分配到堆中。

https://blog.csdn.net/qq_32575047/article/details/81214178
https://blog.csdn.net/somnusrush/article/details/76027122
https://www.jianshu.com/p/3ecc626ce304


GC的常见算法,CMS以及G1的垃圾回收过程,CMS的各个阶段哪两个是Stop the world的,CMS会不会产生碎片,G1的优势。
几种算法的区别体现在对年老代的回收。

PS
mark-copy(stp)
年轻代的垃圾算法
标记-复制,将Eden区的和Survior区复制到另一个S区,并且标记存活次数。

CMS(current mark sweep)
年老代的垃圾算法
initial mark(stp): 第一次标记,从root节点出发,寻找第一个节点停止
concurrent mark(不stp): 并发标记,从initial mark的节点开始标记非空节点
concurrent-preclean(不stp):预清理过程。
remark(stp):由于concurrent mark 不stp,没有完全标记所有的可达对象,需要重新标记一次
concurrent sweep(不stp):将所有未标记的对象清理
concurrent-reset(不stp): 重置内部数据结构
cms是会产生内存碎片的。
cms是基于“标记-清除”算法的收集器,这意味着垃圾回收完成后会产生大量的内存碎片,
当大对象没有足够的连续空间来分配时,不得不提前触发一次Full GC,增加stp的时间。

G1
garbage first的算法:
initial mark(stp): 和cms是一样的操作,同时发生是minor gc。
root region scanning(stp):在初始标记的存活区扫描对老年代的引用,并标记被引用的对象。(共用Minor gc的操作)
concurrent mark(不stp): 并发标记,从initial mark的节点开始标记非空节点,
计算每个 region的对象存活率,方便后面的clean up阶段使用
remark(stp):由于concurrent mark 不stp,没有完全标记所有的可达对象,需要重新标记一次
cleanup(不stp): 清除空Region(没有存活对象的),加入到free list。只是回收没有对象的region,不需要stp。
g1和cms的区别:
g1的内存组织方式变了,不是连续的内存空间,
而是一个个region(分为E(Eden)、S(Survivor)、O(Old)、H(Humongous))。
remark阶段再标记的算法变了,g1的算法是SATB(snapshot-at-the-begining)。
jdk 11 g1作为默认的垃圾回收器。
优势:
G1是一个有整理内存过程的垃圾收集器,不会产生很多内存碎片。
G1的Stop The World(STW)更可控,G1在停顿时间上添加了预测机制,用户可以指定期望停顿时间。

https://tech.meituan.com/g1.html


标记清除和标记整理算法的理解以及优缺点。

标记 -清除算法(Mark-Sweep)
  “标记-清除”算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:
首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。
之所以说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其缺点进行改进而得到的。
它的主要缺点有两个:
(1)效率问题:标记和清除过程的效率都不高;
(2)空间问题:标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,
碎片过多会导致大对象无法分配到足够的连续内存,从而不得不提前触发GC,甚至Stop The World。
标记-整理(Mark-Compact)
   复制收集算法在对象存活率较高时就要执行较多的复制操作,效率将会变低。
更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,
以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法。    
根据老年代的特点,有人提出了另外一种“标记-整理”(Mark-Compact)算法,
标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,
而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

https://blog.csdn.net/wuzhiwei549/article/details/80563134

eden survivor区的比例,为什么是这个比例,eden survivor的工作过程。

默认比例是8:1:1。
因为年轻代中的对象基本都是朝生夕死的(80%以上),所以在年轻代的垃圾回收算法使用的是复制算法。
年轻代的出生在eden区,随着一次gc,由Eden区copy到From Survivor区,年龄+1。
再次回收,由From Survivor和Eden区copy到To Survivor区。年龄超过8岁,进入年老代。

https://www.jianshu.com/p/534ab3c8335f
 

JVM如何判断一个对象是否该被GC,可以视为root的都有哪几种类型。

GC roots。如果从一个对象没有到达根对象的路径,或者说从根对象开始无法引用到该对象,该对象就是不可达的。
gc roots:
    1. 虚拟机(JVM)栈中引用对象 
        每个方法执行的时候,jvm都会创建一个相应的栈帧(栈帧中包括操作数栈、局部变量表、运行时常量池的引用),
        栈帧中包含这在方法内部使用的所有对象的引用(当然还有其他的基本类型数据),当方法执行完后,该栈帧会从虚拟机栈中弹出
    2.方法区中的类静态属性引用对象
    3.方法区中常量引用的对象(final 的常量值)
    4.本地方法栈JNI的引用对象

https://blog.csdn.net/u012941811/article/details/52427372

强软弱虚引用的区别以及GC对他们执行怎样的操作。

强引用:
垃圾回收器绝不会回收它
当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。
软引用:
如果内存空间不足了,就会回收这些对象的内存
可用来实现内存敏感的高速缓存。如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
弱引用:
更短暂的生命周期,不管当前内存空间足够与否,都会回收它的内存。
如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
虚引用:
虚引用不会决定对象的生命周期,在任何时候都可能被垃圾回收器回收。
虚引用必须和引用队列(ReferenceQueue)联合使用。

https://blog.csdn.net/panyongcsd/article/details/46605613

Java是否可以GC直接内存。

NIO的Buffer提供了一个可以不经过JVM内存直接访问系统物理内存的类——DirectBuffer。
 DirectBuffer类继承自ByteBuffer,但和普通的ByteBuffer不同,普通的ByteBuffer仍在JVM堆上分配内存,
 其最大内存受到最大堆内存的限制;而DirectBuffer直接分配在物理内存中,并不占用堆空间,其可申请的最大内存受操作系统限制。
(Note:DirectBuffer并没有真正向OS申请分配内存,其最终还是通过调用Unsafe的allocateMemory()来进行内存分配。不过JVM对Direct Memory可申请的大小也有限制,可用-XX:MaxDirectMemorySize=1M设置,这部分内存不受JVM垃圾回收管理。)
在JVM堆分配内存(allocate)相比,直接内存分配(allocateDirect)的访问性能更好,但分配较慢。

https://www.cnblogs.com/z-sm/p/6235157.html?utm_source=itdadao&utm_medium=referral
http://www.importnew.com/21998.html

Java类加载的过程。

加载、链接(验证、准备、解析)、初始化。
加载:把class字节码文件从各个来源通过类加载器装载入内存中。
    字节码来源。一般的加载来源包括从本地路径下编译生成的.class文件,从jar包中的.class文件,从远程网络,以及动态代理实时编译
    类加载器。一般包括启动类加载器,扩展类加载器,应用类加载器,以及用户的自定义类加载器。
验证:主要是为了保证加载进来的字节流符合虚拟机规范,不会造成安全错误。    
准备:主要是为类变量(注意,不是实例变量)分配内存,并且赋予初值。是Java虚拟机根据不同变量类型的默认初始值。
解析:将常量池内的符号引用替换为直接引用的过程。
    符号引用。即一个字符串,但是这个字符串给出了一些能够唯一性识别一个方法,一个变量,一个类的相关信息。
    直接引用。可以理解为一个内存地址,或者一个偏移量。比如类方法,类变量的直接引用是指向方法区的指针;
    而实例方法,实例变量的直接引用则是从实例的头指针开始算起到这个实例变量位置的偏移量
初始化:主要是对类变量初始化,是执行类构造器的过程。对static修饰的变量或语句进行初始化。

https://blog.csdn.net/ln152315/article/details/79223441
https://www.cnblogs.com/xiaoxian1369/p/5498817.html

 

双亲委派模型的过程以及优势。

实现双亲委派模型的代码都集中在java.lang.ClassLoader的loadClass()方法中:  
首先会检查请求加载的类是否已经被加载过;  
若没有被加载过:  
递归调用父类加载器的loadClass();  
父类加载器为空后就使用启动类加载器加载;  
如果父类加载器和启动类加载器均无法加载请求,则调用自身的加载功能。
优点;
Java类伴随其类加载器具备了带有优先级的层次关系,确保了在各种加载环境的加载顺序。  
保证了运行的安全性,防止不可信类扮演可信任的类。

https://blog.csdn.net/inspiredbh/article/details/74889654
https://blog.csdn.net/qq_38182963/article/details/78660779

 

常用的JVM调优参数。


trace 跟踪:
1. 打印GC的简要信息:
-verbose:gc
-XX:+PrintGC
2. 打印GC详细信息:(生产不要用)
-XX:+PrintGCDetails
3. 指定GC log的位置:
-Xloggc:log/gc.log
4. 类加载信息:
-XX:+TraceClassLoading
5. 堆内存设置:
-Xms1g   -Xmx1g
6. 导出OOM的路径:
-XX:HeapDumpPath=d:/a.dump
7. 初始堆大小
-Xms
8. 最大堆大小
-Xmx


dump文件的分析。


jmap -dump:file=文件名.dump [pid]
jdk自带的visualvm


Java有没有主动触发GC的方式(没有)。


System.gc();
// 或者下面,两者等价
Runtime.getRuntime().gc();
只是通知gc,并没有执行。


内存泄漏和内存溢出的区别和联系

常发性内存泄漏:
发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
偶发性内存泄漏:
发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。
对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
一次性内存泄漏:发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。
比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。
隐式内存泄漏:程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。
严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。
不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。
内存溢出的原因及解决方法:

内存溢出原因: 
内存中加载的数据量过于庞大,如一次从数据库取出过多数据; 
集合类中有对对象的引用,使用完后未清空,使得JVM不能回收; 
代码中存在死循环或循环产生过多重复的对象实体; 
使用的第三方软件中的BUG; 
启动参数内存值设定的过小
内存溢出的解决方案: 
修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。
对代码进行走查和分析,找出可能发生内存溢出的位置。


https://blog.csdn.net/ruiruihahaha/article/details/70270574

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

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

相关文章

[css] 标签、class和id选择器三者的区别是什么?分别在什么时候用?

[css] 标签、class和id选择器三者的区别是什么?分别在什么时候用? 标签选择器:tag{} 选取对应的标签例如 a span div class选择器:.class-name{} 选取对应class-name的元素 id选择器:#id-name{} 选取对应id的元素 其中…

web前端开发怎么样学习?看这份web前端学习路线

前端开发是创建Web页面或app等前端界面呈现给用户的过程。前端开发通过HTML,CSS及JavaScript以及衍生出来的各种技术、框架、解决方案,来实现互联网产品的用户界面交互。它从网页制作演变而来,名称上有很明显的时代特征。在互联网的演化进程中…

今天分享一下做支付宝小程序遇到的坑。ISV权限不足,建议在开发者中心检查对应功能是否已经添加。验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享一下做支付宝小程序遇到的坑。pom版本 <!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java --><dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-j…

[css] 举例说明时间、频率、角度、弧度、百分度的单位分别是哪些?

[css] 举例说明时间、频率、角度、弧度、百分度的单位分别是哪些&#xff1f; 时间: s, ms频率: Hz角度: deg弧度: rad百分度: grad个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起…

[洛谷P4918]信仰收集

题目背景 随着各种势力的迁入,守矢神社丧失了不少信仰现在,为了挽回香火日益惨淡的神社,八坂神奈子派遣神社的风祝早苗去人类村落收集信仰 题目描述 你可以将村落看成一个m个点的有向无环图(编号从1−m),其中在某些点上有n簇待收集的信仰(每一簇都有一定的数量),图中有k有向边,…

Will not attempt to authenticate using SASL | dubbo项目启动特别慢,拉取 zookeeper 服务日志打印特别慢

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享一下使用dubbo遇到的几个问题。 1. cause: KeeperErrorCode ConnectionLoss for /dubbo/ xxx 异常如下&#xff1a; pid9965&qos.accept.foreign.ipfalse&qos.enabletrue&qos.port10887&timestamp1567…

[css] 你有用过table布局吗?说说你的感受

[css] 你有用过table布局吗&#xff1f;说说你的感受 用来做列表排版还是很不错的&#xff0c;但是要想用的好&#xff0c;还是要对table有比较多的了解。 比如实现表头固定&#xff0c;表内容超出滚动的效果等个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放…

Java基础——类加载机制

什么叫类加载 JVM把 .class 字节码文件加载到内存&#xff0c;并进行相关的校验、解析、初始化&#xff0c;最终转换为虚拟机可用的JAVA类型的过程&#xff0c;称为JVM类加载机制。 &#xff08;当然&#xff0c;JVM并不关心class文件的来源&#xff0c;什么&#xff1f;什么叫…

redis集群搭建【简版】

大家好&#xff0c;我是烤鸭&#xff1a; 今天分享一下redis集群安装&#xff0c;写的比较简单&#xff0c;就是做个记录。 1. 下载&安装 wget http://download.redis.io/releases/redis-5.0.4.tar.gz tar -zxvf redis-5.0.4.tar.gz 解压并编译 https://redis.io/ 2.…

[css] 说说你对设备像素比的理解

[css] 说说你对设备像素比的理解 DPR 物理像素与逻辑像素的比个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

x-shell 通过堡垒机连接 ssh多个机器 自动化脚本

大家好&#xff0c;我是烤鸭&#xff1a; 1. 连接vpn 这一步就没什么说的了。我们用的easyconnect。登录后弹出堡垒机页面。 easyconnect 官网&#xff1a;https://sslvpn.zjweu.edu.cn/com/installClient.html 2. 登录堡垒机账号 登录堡垒机之后&#xff0c;如图&#xff…

Python 创建和使用类

python创建和使用类的方法如下 # class Dog(): # def __init__(self,name,age): # self.namename # self.ageage # # def sit(self): # print(self.name.title()"is now sitting") # # def roll_over(self): # print(se…

[css] 说下你对cursor属性的理解

[css] 说下你对cursor属性的理解 cursor 是鼠标光标的属性。可以给元素设置不同的cursor属性来使鼠标在不同的位置显示不同的形状。 值 描述 url 需使用的自定义光标的 URL。注释&#xff1a;请在此列表的末端始终定义一种普通的光标&#xff0c;以防没有由 URL 定义的可用光标…

mybatis 执行插入操作,insert 返回1,数据库中无数据。数据库中数据的创建时间和插入执行时间不一致。

大家好&#xff0c;我是烤鸭&#xff1a; 今天记录一下线上的问题&#xff0c;由于不是我们组的代码&#xff0c;所以没参与全程&#xff0c;只是最后有幸听各位大佬探讨解决方案。mybatis 执行插入操作&#xff0c;insert返回1&#xff0c;日志记录和接口返回都正常&#xff0…

敏捷软件开发学习笔记(四)之结构型设计模式

PHP结构型设计模式 参考 设计模式PHP 设计模式全集 2018什么是结构型是设计模式 结构型模式讲的是如何将类和对象按照某种布局组成更大的结构。它分为类结构型模式和对象结构型模式&#xff0c;其中类结构型模式采用继承机制来组织接口和类&#xff0c;其中对象结构型模式采用组…

[css] position的relative和absolute定位原点是哪里?

[css] position的relative和absolute定位原点是哪里&#xff1f; absolute: 定位原点为第一个position不为static的父级元素的左上角。 可以基于该特性实现height:100%生效 relative&#xff1a;定位原点为元素本身的所在位置。 relative的偏移量设置会导致显示效果和定位原点…

javax.mail.MessagingException: while sending message;Connection reset by peer: socket write error

大家好&#xff0c;我是烤鸭&#xff1a; 阿里云邮件推送服务报错。当你也使用阿里云的邮件推送服务提示上面这个错误的话&#xff0c;我先告诉你原因和目前能想到的解决方案。 解决思路&#xff1a; 1. 换企业邮箱&#xff0c;阿里的上限15M&#xff0c;网易的不知道&…

李晓菁201771010114《面向对象程序设计(java)》第十三周学习总结

理论知识&#xff1a;事件处理 1.事件源&#xff1a;能够产生事件的对象都可以成为事件源&#xff0c;如文本框&#xff0c;按钮等。一个事件源是一个能够注册监听器并向监听器发送事件对象的对象。 2.事件监听器&#xff1a;事件监听器对象接收事件源发送的通告&#xff08;事…

[css] 过渡和动画的区别是什么?

[css] 过渡和动画的区别是什么&#xff1f; 相同&#xff1a;都会让你的页面元素动起来 区别&#xff1a; 过渡 transition1.需要事件触发&#xff0c;比如hover&#xff0c;focus&#xff0c;checked , js改, media query 2.一次性的 3.只能定义开始和结束状态&#xff0c;不…

记一次 OOM 的原因和处理 出现大量 close_wait,项目无法访问 activeMq和 poi 出现的 OOM

大家好&#xff0c;我是烤鸭: 记一次项目无法访问的事件和处理。由于某个模块每隔几天就会出现无法访问&#xff0c;目前的最简单粗暴的方法就是重启。 1. 现象 项目内日志打印正常&#xff0c;经过dubbo的rpc服务和接口调用正常。http接口无法访问。提示nginx 502。 2.…