面试题-重点
31、为什么需要双亲委派模型
防止内存中出现多份同样的字节码
32、导致Full GC 一般有哪些情况
(1).新生代设置过小 一是新生代 GC 次数非常频繁,增大系统消耗;二是导致大对象直接进入旧生代,占据了旧生代剩余空间,诱发 Full GC (2). 新生代设置过大 一是新生代设置过大会导致旧生代过小(堆总量一定),从而诱发 Full GC;二是新生代 GC耗时大幅度增加 (3). Survivor 设置过小 导致对象从 eden 直接到达旧生代 (4). Survivor 设置过大 导致 eden 过小,增加了 GC 频率 一般说来新生代占整个堆 1/3 比较合适 GC 策略的设置方式 (5). 吞吐量优先 可由-XX:GCTimeRatio=n 来设置 (6). 暂停时间优先 可由-XX:MaxGCPauseRatio=n 来设置
33、Minor GC,Full GC触发条件
Minor GC 触发条件:当 Eden 区满时,触发 Minor GC。 Full GC 触发条件: (1)调用 System.gc 时,系统建议执行 Full GC,但是不必然执行 (2)老年代空间不足 (3)方法区空间不足 (4)通过 Minor GC 后进入老年代的平均大小大于老年代的可用内存 (5)由 Eden 区、From Space 区向 To Space 区复制时,对象大小大于 To Space 可存,则把 该对象转存到老年代,且老年代的可用内存小于该对象大小
34、JVM性能调优
1、设定堆内存大小 -Xmx:堆内存最大限制。 2、设定新生代大小。 新生代不宜太小,否则会有大量对象涌入老年代 -XX:NewSize:新生代大小 -XX:NewRatio 新生代和老生代占比 -XX:SurvivorRatio:伊甸园空间和幸存者空间的占比 3、设定垃圾回收器 年轻代用 -XX:+UseParNewGC 年老代用-XX:+UseConcMarkSweepGC
35、Java中堆和栈有什么区别?
最主要的区别就是栈内存用来存储局部变量和方法调用。 而堆内存用来存储 Java 中的对象。无论是成员变量,局部变量,还是类变量,它们指向的对象都存储在堆内存中。 独有还是共享 栈内存归属于单个线程,每个线程都会有一个栈内存,其存储的变量只能在其所属线程中可见,即栈内存可以理解成线程的私有内存。 而堆内存中的对象对所有线程可见。堆内存中的对象可以被所有线程访问。 异常错误 如果栈内存没有可用的空间存储方法调用和局部变量,JVM 会抛出java.lang.StackOverFlowError。 而如果是堆内存没有可用的空间存储生成的对象,JVM 会抛出 java.lang.OutOfMemoryError。 空间大小 栈的内存要远远小于堆内存,如果你使用递归的话,那么你的栈很快就会充满。如果递归没有及时跳出,很可能发生 StackOverFlowError 问题。
36、常见的垃圾回收算法有哪些?简述其原理
GC 最基础的算法有三种: 标记 -清除算法、复制算法、标记-压缩算法,我们常用的垃圾回收器一般都采用分代收集算法。 标记 -清除算法,“标记-清除”(Mark-Sweep)算法,如它的名字一样,算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象。 复制算法,“复制”(Copying)的收集算法,它将可用内存按容量划分为大小相等的两块, 每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。 标记-压缩算法,标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存 分代收集算法,“分代收集”(Generational Collection)算法 ,把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。
37、解释栈(stack),堆(heap)和方法区(method area)的用法?
通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的现场保存都使用 JVM 中的栈空间;而通过 new 关键字和构造器创建的对象则放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分代收集算法,所以堆空间还可以细分为新生代和老生代,再具体一点可以分为 Eden、Survivor(又可分为 From Survivor 和 ToSurvivor)、Tenured;方法区和堆都是各个线程共享的内存区域,用于存储已经被 JVM 加载的类信息、常量、静态变量、JIT 编译器编译后的代码等数据;程序中的字面量(literal)如直接书写的 100、”hello”和常量都是放在常量池中,常量池是方法区的一部分,。栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过 JVM的启动参数来进行调整,栈空间用光了会引发 StackOverflowError,而堆和常量池空间不足则会引发 OutOfMemoryError。
38、什么是类的加载?
类的加载指的是将类的.class 文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Class 对象,用来封装类在方法区内的数据结构。 类的加载的最终产品是位于堆区中的 Class 对象,Class 对象封装了类在方法区内的数据结构,并且向 Java 程序员提供了访问方法区内的数据结构的接口。
39、类加载器有哪些?
启动类加载器:Bootstrap ClassLoader,负责加载存放在 JDK\jre\lib(JDK 代表 JDK 的安装目录,下同)下,或被-Xbootclasspath 参数指定的路径中的,并且能被虚拟机识别的类库扩展类加载器:Extension ClassLoader,该加载器由 sun.misc.Launcher$ExtClassLoader 实现, 它负责加载 DK\jre\lib\ext 目录中,或者由 java.ext.dirs 系统变量指定的路径中的所有类库(如javax.*开头的类),开发者可以直接使用扩展类加载器。应用程序类加载器:Application ClassLoader,该类加载器由 sun.misc.Launcher$AppClassLoader来实现,它负责加载用户类路径(ClassPath)所指定的类,开发者可以直接使用该类加载器
40、Java对象创建过程?
1.JVM 遇到一条新建对象的指令时首先去检查这个指令的参数是否能在常量池中定义到一个类的符号引用。然后加载这个类(类加载过程在后边讲) 2.为对象分配内存。一种办法“指针碰撞”、一种办法“空闲列表”,最终常用的办法“本地线程缓冲分配(TLAB)” 3.将除对象头外的对象内存空间初始化为 0 4.对对象头进行必要设置
原文地址:https://blog.csdn.net/m0_68933188/article/details/136154096
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!