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 }
复制代码

 

posted @   谁怕?一蓑烟雨任平生  阅读(82)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示