JVM系列六-常见问题
1、谈谈你对JVM的理解?java8的虚拟机有什么更新?
JVM是Java虚拟机的意思。它是建立在操作系统之上的,它由类加载器子系统、本地方法栈、Java栈、程序计数器、方法区、堆、本地方法库、本地方法接口、执行引擎组成。
其中类加载器用于把要执行的java文件加载进内存中的方法区;
本地方法栈是类中一段特殊的标记,用native标记,用于加载操作系统底层的资源;
java栈中存储的是8种基本数据类型+引用类型+实例方法;
程序计数器是线程私有的,其实就是一个指针,里边记录了A方法执行完毕后,下一个要执行的方法是哪一个;
方法区里边主要存储由类加载子系统加载进来的Class文件;
堆中存储的主要实例对象;
执行引擎主要用于执行java代码;
2、什么是OOM?什么是StackOverFlowError?有哪些方法分析?
(1)OOM是堆内存溢出,产生原因:堆空间是一定的,当堆空间的内存空间不满足创建对象所需要的内存时,就会抛出OOM异常。
(2)StackOverFlowError是栈内存溢出。栈中主要存储的是8种基本数据类型+引用类型+实例方法,栈空间和堆空间一样,空间也是有限的,当存储进栈空间的容量大于栈当前的空闲容量时,就会报栈内存溢出。
2.1.1、OOM案例
1 package com.atguigu.jvm; 2 3 import java.util.Random; 4 5 /** 6 * 写一段程序导致OOM 7 * -Xms10m -Xmx10m -XX:+PrintGCDetails 8 */ 9 public class OOMDemo { 10 public static void main(String[] args) { 11 String str = "www.atguigu.com" ; 12 while(true) { 13 str += str + new Random().nextInt(88888888) + new Random().nextInt(999999999) ; 14 } 15 } 16 }
2.1.2、StackOverFlowError案例
1 package com.atguigu.jvm; 2 3 /** 4 * 写一段程序导致栈内存溢出 5 */ 6 public class StackOverFlowErrorDemo { 7 public static void main(String[] args) { 8 System.out.println("1111"); 9 m1(); 10 System.out.println("4444"); 11 12 } 13 14 public static void m1(){ 15 m1(); 16 } 17 18 }
3、JVM的常用参数调优你知道哪些?
- -Xms 设置堆内存的最小空间,默认为物理内存的1/64
- -Xmx 设置堆内存的最大空间,默认为物理内存的1/4
- -Xmn 设置新生区的空间
- -XX:+PrintGCDetails 输出详细的GC日志
4、谈谈JVM中,你对类加载器的认识?
JVM中的类加载器有3种,分别是启动类加载器Bootstrap、扩展类加载器Extension、系统类加载器Application。类加载器的主要作用是:把要执行的类加载进方法区,供用于创建对象使用。
5、什么是双亲委派机制?什么是沙箱安全机制?
所谓双亲委派机制是指:当一个类加载器收到了类加载请求,它首先不会尝试自己去加载这个类,而是把这个请求委派给它的父类去完成,每一层次的加载器都是如此,因此所有的加载请求都应该传送到启动类加载器中,只有当父类加载器反馈自己无法完成这个请求时(在它的路径下没有找到需要加载的Class),子类加载器才会尝试自己去加载。
采用双亲委派机制的好处是可以保证沙箱安全,即自己写的代码即使和jdk自带的启动类加载器的Class文件同包同名,也不会污染源代码。比如加载位于rt.jar包中的类java.lang.Object,不管是采用哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就保证了使用不同的类加载器最终得到的都是同一个Object对象。
6、JVM的初始内存和最大内存怎么配置?
可以通过虚拟机的-Xms、-Xmx来配置,而且这俩配置的大小应该一样,避免GC争抢内存导致的不稳定,忽高忽低。
7、调整栈大小就能保证不出现溢出吗?
不能保证,如果方法递归是个死循环还是会出现溢出,通过增加栈内存大小只能保证方法执行次数变多。
8、分配的栈内存越大越好吗?
不是,栈内存太大会导致其他线程的内存空间有限。
9、垃圾回收是否涉及到栈?
不涉及。
栈也叫栈内存,主管Java程序的运行,是在线程创建时创建,它的生命期是跟随线程的生命期,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题,只要线程一结束该栈就Over,生命周期和线程一致,是线程私有的
10、方法中定义的局部变量是否线程安全?
具体问题得具体分析
1 package com.atguigu.jvm; 2 3 /** 4 * StringBuilder线程不安全 5 */ 6 public class StringBuilderDemo { 7 public static void main(String[] args) { 8 StringBuilder sb = new StringBuilder(); 9 new Thread(()->{ 10 sb.append("a"); 11 sb.append("b"); 12 }).start(); 13 method(sb); 14 System.out.println(sb); 15 } 16 17 private static void method(StringBuilder sb) { 18 sb.append("a"); 19 sb.append("b"); 20 } 21 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义