知识图库
Java知识库
JDK线程池实现原理
Java中的强、软、弱、虚引用
深入拆解Java虚拟机
01 开篇词 | 为什么我们要学习Java虚拟机?
02 Java代码是怎么运行的?
03 Java的基本类型
04 Java虚拟机是如何加载Java类的?
05 JVM是如何执行方法调用的?(上)
06 JVM是如何执行方法调用的?(下)
7 JVM是如何处理异常的?
Java面试常见问题整理
Java面试常见问题-Java 基础篇
Java面试常见问题-Jvm篇
Java面试常见问题-并发篇
Android知识库
Kotlin编程第一课
1 开篇词 | 入门Kotlin有多容易,精通Kotlin就有多难
2 Kotlin基础语法:正式开启学习之旅
3 面向对象:理解Kotlin设计者的良苦用心
4 Kotlin原理:编译器在幕后干了哪些“好事”?
5 实战:构建一个Kotlin版本的四则运算计算器
6 object关键字:你到底有多少种用法?
7 扩展:你的能力边界到底在哪里?
8 高阶函数:为什么说函数是Kotlin的“一等公民”?
9 实战:用Kotlin写一个英语词频统计程序
10 加餐一 | 初识Kotlin函数式编程
11 委托:你为何总是被低估?
12 泛型:逆变or协变,傻傻分不清?
13 注解与反射:进阶必备技能
14 实战:用Kotlin实现一个网络请求框架KtHttp
15 加餐二 | 什么是“表达式思维”?
16 加餐三 | 什么是“不变性思维”?
17 加餐四 | 什么是“空安全思维”?
18 春节刷题计划(一)| 当Kotlin遇上LeetCode
19 春节刷题计划(二)| 一题三解,搞定版本号判断
20 春节刷题计划(三)| 一题双解,搞定求解方程
21 春节刷题计划(四)| 一题三解,搞定分式加减法
22 什么是“协程思维模型”?
23 如何启动协程?
24 挂起函数:Kotlin协程的核心
25 Job:协程也有生命周期吗?
26 Context:万物皆为Context?
27 实战:让KtHttp支持挂起函数
28 期中考试 | 用Kotlin实现图片处理程序
29 题目解答 | 期中考试版本参考实现
30 Channel:为什么说Channel是“热”的?
31 Flow:为什么说Flow是“冷”的?
32 select:到底是在选择什么?
33 并发:协程不需要处理同步吗?
34 异常:try-catch居然会不起作用?坑!
35 实战:让KtHttp支持Flow
36 答疑(一)| Java和Kotlin到底谁好谁坏?
37 集合操作符:你也会“看完就忘”吗?
38 协程源码的地图:如何读源码才不会迷失?
39 图解挂起函数:原来你就是个状态机?
40 加餐五 | 深入理解协程基础元素
41 launch的背后到底发生了什么?
42 Dispatchers是如何工作的?
43 CoroutineScope是如何管理协程的?
44 图解Channel:如何理解它的CSP通信模型?
45 图解Flow:原来你是只纸老虎?
46 Java Android开发者还会有未来吗?
47 Kotlin与Jetpack简直是天生一对!
48 用Kotlin写一个GitHub Trending App
49 结课测试 | “Kotlin编程第一课”100分试卷等你来挑战!
50 结束语 | 不忘初心
Android Framework 教程—基础篇
01 Ubuntu 使用快速入门
02 Make 构建工具入门
03 理解 Unicode UTF-8 UTF-16 UTF-32
04 Linux Shell 脚本编程入门1——核心基础语法
05 SeAndroid 使用极速上手
06 理解 C++ 的 Memory Order
07 AOSP 极速上手
08 系统开发工具推荐
09 添加 Product
运动相关知识
爱上跑步
01 开篇词 | 跑步,不那么简单的事儿
02 跑两步就喘了,是不是我不适合跑步?
03 正确的跑步姿势是什么样的?
04 为什么跑步要先热身?
05 怎样制定你的第一个10公里跑步计划?
06 快跑和慢跑,哪个更燃脂?
07 普通跑步者应该如何选择跑鞋?
08 买跑步装备,不要踩这些坑儿
09 跑步前到底应不应该吃东西?
10 跑步到底伤不伤膝盖?
11 参加了20场马拉松,我是如何准备的?
12 除了马拉松,还能参加哪些跑步赛事?
13 热点问题答疑 :跑完第二天浑身疼,还要不要继续跑?
健身房计划
[DeepSeek]减脂塑形计划
【DeepSeek】训练周期安排
每日餐饮热量控制
减脂期间食物推荐避坑指南
HarmonyOS知识库
其他知识类目
心理学相关
如何学点心理学——关于非专业人士学心理学的一点建议
投射性认同
-
+
首页
Java面试常见问题-Jvm篇
1. ### Java 类加载器有几种?   2. ### 说一下有哪些类加载场景?  3. ### 说说 Java 类加载机制是什么?说说 new 创建一个普通对象的过程? - 类加载的过程包括了:加载、验证、准备、解析、初始化。  - new 创建一个普通对象的过程如下: - 检测类是否被加载过 - 为对象分配内存 - 为分配的内存空间初始化为 0 - 对对象进行其他相关设置 - 执行 init 方法  4. ### 说说类的生命周期? 注意类生命周期和对象声明周期,类生命周期主要有以下几个阶段:   5. ### 什么是双亲委派模型?  6. ### 如何破坏双亲委派模型?  7. ### 能不能自己也写一个 java.lang.String 类? 可以写,能编译,但是不能 run。禁止使用包名:java.开头的包名。 定义一个普通类: ```java package java.lang; public class MyTest { public MyTest() { } public MyTest(String str, int a) { } public int length(){ return 10; } public static void main(String[] args) { MyTest myTest =new MyTest("lang",1); myTest.length(); } } ``` 运行:  具体校验的源码地方:  **结论就是定义包目录的时候,不能以 java. 开头。** 8. ### 说一下 JVM 运行时数据区有哪些?分别说一下它们的功能 此题我想用我的方法说,不像网上一堆一堆抄书上的,希望能对大家有所帮助,如果没多大帮助,那可以网上找个看看,只能说抱歉了。  #### 下面我们直入主题: >d **每个线程单独拥有的**:程序计数器、Java 虚拟机栈、本地方法栈 >d **所有线程都共同有的:** 方法区、堆 >i 如果你在 Java 代码里创建一个线程,相应 JVM 虚拟机中就创建与之对应的程序计数器、Java 虚拟机栈、本地方法栈,同时方法区和堆是在虚拟机启动就已经有了。 - #### 程序计数器 可以简单理解为:程序计数器是记录执行到你代码的的第几行了,每个线程各自对应自己的程序计数器。 - #### Java 虚拟机栈 虚拟机会为每个线程分配一个虚拟机栈,每个虚拟机栈中都有若干个栈帧,每个栈帧中存储了局部变量表、操作数栈、动态链接、返回地址等。一个栈帧就对应 Java 代码中的一个方法,当线程执行到一个方法时,就代表这个方法对应的栈帧已经进入虚拟机栈并且处于栈顶的位置,每一个 Java 方法从被调用到执行结束,就对应了一个栈帧从入栈到出栈的过程。一个线程的生命周期和与之对应的 Java 虚拟机栈的生命周期相同。 一个线程进来就创建虚拟机栈,该线程调用的方法就是栈帧,进入方法,栈帧就入栈(虚拟机栈),出方法就是出虚拟机栈。可以通过下面两张图进行理解:   - #### 本地方法栈 和 Java 虚拟机栈类似,Java 虚拟机栈针对的是 Java 方法,而本地方法栈针对的 native 修饰的方法。 - #### 堆 JVM 几乎所有的对象的内存分配都在堆里。由于对象是有生命周期的,所以把堆又分成了新生代和老年代。 - 新生代和老年代大小比例 = 1:2(默认)。 - 新生代又分为 Eden、S0、S1 区域,Ede:S0:S1=8:1:1 - 大多数对象在 Eden 区出生和死亡。 >i Eden 区存活下来的对象进入 S0 区,S0 区活下来的对象放到 S1,S1 区活下来的对象放到 S0 区,这过程中 S0 和 S1 至少有一个区域是空着的。并且对象每次倒腾一次自己的年龄就加 1,直达加到 15 岁的时候,就直接入老年代了。有的大对象可以直接进入老年代,条件是把该对象的大小以及达到了能直接进入老年代的条件了(阈值可以设置)。  - #### 方法区 先按照图中的关键字回答。但是方法区由于 JDK 版本有所变动。  回答的时候,一定要说一下方法区由于 JDK 版本有所变动。版本变动情况如下:  9. ### 方法区和永久代有什么区别? 之前有小伙伴也问过我,方法区和永久代到底是什么区别?这么说吧:永久代又叫 Perm 区,只存在于 HotSpot JVM 中,并且只存在于 JDK 1.7 和之前的版本中,JDK 1.8 中已经彻底移除了永久代,JDK 1.8 中引入了一个新的内存区域叫 metaspace。 并不是所有的 JVM 中都有永久代,IBM 的 9,Oracle 的 JRocket 都没有永久代。 永久代是实现层面的东西。 永久代里面存的东西基本上就是方法区规定的那些东西。 因此,我们可以说,在 JDK 1.7 中永久代是方法区的一种实现,当然,在 HotSpot JDK 1.8 中 metaspace 可以看成是方法区的一种实现。 10. ### JVM 运行时数据区哪些地方会产生内存溢出? Java 虚拟机栈、本地方法栈、Java 堆、方法区,其实就是除了程序计数器以外的几个都会发生 OOM。 >w 值对应的几个区也简要的说一下:  10. ### 为什么要用 metaspace 替换 permspace 呢? 在 JDK 1.8 之前的 HotSpot 实现中,类的元数据如方法数据、方法信息(字节码、栈和变量大小)、运行时常量池、已确定的符号引用和虚方法表等被保存在永久代中,32 位默认永久代的大小为 64M,64 位默认为 85M,可以通过参数 -XX:MaxPermSize 进行设置,一旦类的元数据超过了永久代大小,就会抛出 OOM 异常。 虚拟机团队在 JDK 1.8 的 HotSpot 中,把永久代从 Java 堆中移除了,并把类的元数据直接保存在本地内存区域(堆外内存),称之为元空间 metaspace(本地内存)。即就是说 JDK 1.8 之前,永久代是在虚拟机中的,而 JDK 1.8 引入的元空间是系统的内存的一部分。理论上取决于 32 位/64 位系统可虚拟的内存大小,可见也不是无限制的,需要配置参数。 另外一方面,咱们在对永久代进行调优的时候是相当费劲,因为永久代的大小不好控制,涉及到很多因素,比如:类的总数、常量池的大小、方法数量等,最无语的是永久代的内存不够了可能会伴随着一次 Full GC。 **下面是 JDK 几个版本中方法区和堆存储的信息的关系:**  #### 总结 1. 字符串存在永久代中,容易出现性能问题和内存溢出。 2. 类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。 3. 永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。 4. 移除永久代是为融合 HotSpot JVM 与 JRockit VM 而做出的努力,因为 JRockit 没有永久代,不需要配置永久代。 11. ### 熟悉哪些 JVM 调优参数? 1. #### 整个堆内存大小 -Xms(初始堆大小)、-Xmx(最大堆大小),为了防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,我们通常把最大、最小设置为相同的值。 2. #### 新生代空间大小 NewRadio:年轻代和年老代将根据默认的比例(1:2)分配堆内存,建议设置为 2 到 4,可以通过调整二者之间的比率 NewRadio 来调整二者之间的大小。也可以针对回收代,比如年轻代,通过 -XX:newSize -XX:MaxNewSize 来设置其绝对大小。同样,为了防止年轻代的堆收缩,我们通常会把 -XX:newSize -XX:MaxNewSize 设置一样大小。 3. #### 方法区(元空间) JDK 1.8:-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m,根据实际情况调整, 可以使用命令 jstat -gcutil pid 查看当前使用率,M 对应的列,根据使用率来定制一个具体的值,建议两个值设置成同样大小。 JDK 1.7:-XX:MaxPermSize=256m -XX:MaxPermSize=256m 永久带。 4. #### GC 日志 -Xloggc:$CATALINA_BASE/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps 记录 GC 日志并不会特别地影响 Java 程序性能,推荐你尽可能记录日志。 5. #### GC 算法 -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 一般来说推荐使用这些配置,但是根据程序不同的特性,其他的也有可能更好。 任何一个 JVM 参数的默认值可以通过 java -XX:+PrintFlagsFinal -version |grep JVMParamName 获取,例如: java -XX:+PrintFlagsFinal -version |grep MetaspaceSize 12. ### Java 对象的引用类型有哪些? 对象引用类型有四类:强引用、软引用、弱引用、虚引用。  13. ### JVM 垃圾回收算法有哪些? 垃圾回收算法共四种:其实我更愿意说成三种,因为分代回收其实不是算法。  14. ### 垃圾收集器有哪些? 目前常见的有如下几种:  - #### Serial 收集器  - #### ParNew 收集器  - #### Parallel scavenge 收集器  - #### Serial Old 收集器  - #### CMS=Concurrent Mark Sweep 收集器  - #### Parallel Old 收集器  - #### G1=Garbage-First 收集器  14. ### 垃圾收集器整合 G1 是新生代和老年代一起搞,不和别人合伙。 Serial:CMS 或者 Serial Old ParNew:CMS 或者 Serial Old Parallel Scavenge:Parallel Old 或者 Serial Old 分代收集器对应 - 新生代收集器:Serial、ParNew、Parallel Scavenge - 老年代收集器:Serial Old、Parallel Old、CMS 整堆收集器:G1 14. ### 说说 JVM 中内存的分配与回收策略 
嘿手大叔
2024年12月24日 11:17
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码