整理的腾讯面试题及答案
程序员文章站
2022-05-06 16:50:06
...
3、JVM调优,工作中怎么用,GC算法和回收策略有哪些
jvm调优的目的是减少GC的频率和Full GC的次数。
Full GC会对整个堆进行整理,因此要尽量减少Full GC的次数。
导致Full GC的原因,
老年代空间满了,调优时尽量让对象在新生代时被回收、让对象在新生代多存活一段时间和不要创建太大的对象以及数组,避免直接在老年代创建对象。
持久代空间不足,增大持久代空间,避免太多静态对象,控制好新生代和老年代的比例。
System.gc()触发,垃圾回收不要手动触发,尽量依靠jvm自身机制触发。
jvm调优方法和步骤:1、监控GC状态,使用各种jvm工具,分析当前jvm参数设置,并且分析当前堆内存快照h和gc日志。
2、生成堆的dump文件
3、分析dump文件
4、分析结果判断是否需要优化,如果满足下面的指标,则一般不需要进行GC:
Minor GC执行时间不到50ms;
Minor GC执行不频繁,约10秒一次;
Full GC执行时间不到1s;
Full GC执行频率不算频繁,不低于10分钟1次;
5、调整GC类型和GC分配
GC算法:引用计数算法、标记清除算法、复制算法、标记整理算法
GC回收策略:可达性分析法、引用计数法
4、Java中线程池是如何实现的? 创建线程池的几个核心构造参数是什么?
线程池的好处:重用已经存在的线程,减少线程的创建和销毁,
控制最大并发的线程数,提高系统资源的使用率避免很多竞争,也避免了死锁
可以提供定时和定期的执行方式,单线程、并发数量的控制等功能。
可以对高并发进行控制。
线程池的实现方法:1、ThreadPoolExecutor:指定线程数的线程池
2、fixedTheadPool:启动固定数的线程池
3、CacheThreadPool:按需分配的线程池
4、ScheduledThreadPoolExecutor:定时定期执行任务的线程池
核心构造参数:corePoolSize:线程的核心线程数
maximumPoolSize:线程允许的最大线程数
keepAliveTime:当前线程池线程总数大于核心线程数时,终止多余空线程的时间
Unit:keepAliveTime参数的时间单位
workQueue:队伍队列,如果线程池达到了核心线程数,并且其它线程处于活动状态的时候,则将新任务放入此队列
threadFactory:定制线程的创建过程
Handler:拒绝策略,当workQueue队满时,采取措施
5、Volatile和Synchronize的区别?
volatile用在变量中,synchronized用于方法和代码块
volatile可以保证可见性和禁止指令重排序不能保证原子性,synchronized可以保证方法的原子性和可见性、一致性、可重入性
volatile的本质是告诉jvm当前变量在寄存器中的值是不确定的,需要从主存中取,synchronized则是锁定当前变量,只有当前线程可以访问该变量,其它线程被阻塞。
volatile不会造成线程的阻塞,synchronized会造成线程的阻塞
volatile标记的变量不会被编译器优化,synchronized标记的变量可以被编译器优化。
6、GC的机制是什么?垃圾回收器的基本原理是什么?是否可以立即回收内存?怎么样主动的通知JVM进行垃圾回收?
jvm主要是对堆以及方法区进行垃圾回收
需要进行回收的对象是已经不存活的对象,判断一个对象是否存活有两种办法,一种是引用计数法,另一种是可达性分析法。
GC分为minor GC和full GC
minor GC的触发条件是:Eden区内存满时,触发minor GC
full GC的触发条件:手动条用System.gc时、老年代空间不足时、方法区空间不足时、
通过minor GC进入老年代的对象平均大小大于老年代的可用内存
由Eden区、From Space区向To Space区复制时,对象大于To Space区内存,则把该对象转移到老年代,且老年代的可用内存小于该对象的大小
GC常用的算法:标记-清除法、复制算法、标记整理算法、分代收集算法
垃圾收集器:串行收集器(Serial收集器)、并行收集器(ParNew、Parallel收集器)、CMS收集器、G1收集器
垃圾回收期的基本原理:对于GC而言,当程序员创建对象的时候GC就开始监控这个对象在内存的地址、大小以及使用情况。GC采用有向图的方法记录和管理堆中所有的对象,通过这种方式来确定哪些对象是可达的哪些对象是不可达的,当确定了不可达对象,就将该对象所占用的内存回收。
7、类加载器及双亲委派模型机制?
Java类的加载时动态的,一开始并不会将所有的类加载完成再运行,而是保证程序的基础类完全加载到jvm中,至于其它类则在需要的时候再加载。这是为了节省内存开销。
Java类的类加载器有三个,对应的三种类分别是:Bootstrap Loader(负责加载系统类)、ExtClassLoader(负责加载扩展类)、AppClassLoader(负责加载应用类)
为了使三个类协调工作,并且解决一个类该有哪个类加载器加载,Java采用了委托模式机制。
委托模式的工作原理:当类加载器需要加载类的时候,先请示Parent(即上一层加载器),在其搜索路径载入,如果找不到则在自己的搜索路径搜索该类,这样的顺序就是加载器自上而下的搜索,因为加载器必须保证基础类的加载,之所以是这种机制是因为如果某人恶意将基础类加载到jvm,委托模型机制会搜索其父类加载器,显然是不可能找到的,自然就不会讲该类加载进来。