JAVA今日面经(一)
1.Java中如何排查内存溢出
1.1内存不足的核心原因
java中内存溢出的原因有两个,JVM堆/非堆内存分配不足,或内存泄漏使可用内存被耗尽,我们需要定位内存消耗大项,和区分内存是泄露还是真的不足
1.2内存为什么会泄露
内存泄露的本质是本来被GC回收的对象被意外持有引用,导致无法回收一直占用内存,最终导致可用内存越来越少,常见场景有静态集合类持有对象引用,长生命周期对象持有段生命周期对象引用,未关闭的IO/连接/监听器,缓存使用不当,线程未停止等
1.3排查步骤
1.3.1确认内存泄漏
通过工具观察堆内存各区域(Eden、Survivor、Old Gen)的使用情况,判断是否存在内存无法释放的情况
分析GC日志,查看Full GC频率,耗时以及内存释放情况。
1.3.2抓取内存快照,即JVM堆在某一时刻的完整镜像
1.3.3分析内存快照
通过工具分析快照,定位泄露对象:
识别异常对象,查看是否有对象数量异常,或者生命周期异常
查看引用链,查看是否有对象被意外劫持导致无法被回收
1.4常用工具
jps:查看进程ID
jstat:实时监控JVM内存和GC状态
jmap:生成堆快照,查看对象分布
jconsole/jvisualvm:图形化工具
2.HashMap的底层原理了解吗?
HashMap是基于红黑树+链表+数组的哈希表实现,用于存储键值对(key—value),其核心原理如下:
2.1哈希计算与扰动处理
当插入或查询数据时,使用key.hashcode()方法获取哈希值,并赋值给一个变量h
再h ^ (h >>> 16):将高 16 位和低 16 位做异或运算,把高位信息混入低位,减少哈希碰撞概率
2.2索引定位
使用(n-1)&hash获取bucket下标,效率比取模高
2.3冲突处理
若桶节点为空,直接放入节点
若存在节点,则逐个比较,若equals()相等则覆盖,若不等于则放到链表尾部
当单个桶内节点数>8&&数组容量>=64时,链表转为红黑树
2.4扩容机制
默认初始容量为16,负载因子0.75
当元素超过阈值16*0.75,数组变成2倍,并且重新分配节点
用(node.hash&oldCap)判断留在原位置还是i+oldCap
