周口网站设计,网站做的一样算不算侵权,公司网站建设与管理的作用,网页怎么制作的什么时候会有内存泄漏#xff0c;怎么排查#xff1f; 答#xff1a;
首先内存泄漏是堆中的一些对象不会再被使用了#xff0c;但是无法被垃圾收集器回收#xff0c;如果不进行处理#xff0c;最终会导致抛出 java.lang.OutOfMemoryError 异常。
内存泄露#xff1a; … 什么时候会有内存泄漏怎么排查 答
首先内存泄漏是堆中的一些对象不会再被使用了但是无法被垃圾收集器回收如果不进行处理最终会导致抛出 java.lang.OutOfMemoryError 异常。
内存泄露
不需要使用的对象被其他对象不正确的引用导致无法回收。对象生命周期过长
内存泄漏的8中情况 大量使用静态集合类HashMap、LinkedList等静态变量的生命周期和JVM程序一致在程序结束之前静态变量不会被释放导致内存泄漏。属于生命周期过长 单例模式的静态特性也会导致生命周期过长如果单例对象持有外部对象的引用会导致外部对象不会被回收。 内部类持有外部类每个非静态内部类都会持有外部类的隐式引用假如a为非静态内部类b为a的外部类如果b包含了大量对象的引用非常占用内存空间那么如果我们创建了非静态内部类a此时即使b对象不再被使用了也无法回收占用内存空间导致内存泄漏。 解决办法如果内部类不需要访问外部类的成员信息可以考虑转换为静态内部类。 各种连接数据库连接、网络连接和IO连接未及时关闭导致大量对象无法回收造成内存泄漏。 变量不合理的作用域一个变量的定义的作用范围大于其适用范围很有可能造成内存泄露。 改变哈希值 当一个对象被存储进HashSet集合中以后就不能修改这个对象中的那些参与计算哈希值的字段了。 否则对象修改后的哈希值与最初存入HashSet集合时的哈希值就不同了这种情况下即使在contains方法使用该对象的当前引用作为参数去HashSet集合中检索对象也将返回找不到对象的结果这也会导致HashSet集合中无法单独删除当前对象造成内存泄漏 为什么改变哈希值之后找不到对象因为根据存入时的哈希值去寻找放入的位置而改变哈希值之后再去查找就按照新的哈希值所对应的位置去查找肯定找不到。 这也是 String 为什么被设置成了不可变类型我们可以放心的把 String 存入 HashSet或者把String当作 HashMap 的 key 值。 public class ChangeHashCodeTest {public static void main(String[] args) {HashSetPoint set new HashSet();Point cc new Point();cc.setX(10); // hashCode 10set.add(cc);cc.setX(20); // hashCode 20System.out.println(set remove set.remove(cc));set.add(cc);System.out.println(set.size set.size());/*** 输出* set remove false* set.size 2*/}
}
class Point {int x;public int getX() {return x;}public void setX(int x) {this.x x;}Overridepublic boolean equals(Object o) {if (this o) return true;if (o null || getClass() ! o.getClass()) return false;Point point (Point) o;return x point.x;}Override public int hashCode() {return x;}
}缓存泄露 一旦把对象引用放入到缓存中他就很容易遗忘。比如之前项目在一次上线的时候应用启动奇慢就是因为代码会加载一个表的数据到缓存中测试环境只有几百条数据而生产环境有几百万的数据。 对于这个问题可以使用WeakHashMap代表缓存此Map的特点是当除了自身有key的引用外此key没有其他引用那么此map会自动丢弃此值。 ThreadLocal ThreadLocal的实现中每个Thread维护一个ThreadLocalMap映射表key是ThreadLocal实例本身value是真正需要存储的Object。 ThreadLocalMap使用ThreadLocal的弱引用作为key如果一个ThreadLocal没有外部强引用来引用它那么系统GC时这个ThreadLocal势必会被回收这样一来ThreadLocalMap中就会出现key为null的Entry就没有办法访问这些key为null的Entry的value。 如果当前线程迟迟不结束的话这些key为null的Entry的value就会一直存在一条强引用链Thread Ref - Thread - ThreaLocalMap - Entry - value永远无法回收造成内存泄漏。 如何解决此问题 第一使用ThreadLocal提供的remove方法可对当前线程中的value值进行移除 第二不要使用ThreadLocal.set(null) 的方式清除value它实际上并没有清除值而是查找与当前线程关联的Map并将键值对分别设置为当前线程和null。 第三最好将ThreadLocal视为需要在finally块中关闭的资源以确保即使在发生异常的情况下也始终关闭该资源。 try {threadLocal.set(System.nanoTime());
} finally {threadLocal.remove();
}
排查内存泄漏
可以查看泄露对象到GC Roots的引用链找到泄露对象在哪里被引用导致无法被回收 JVM常见配置 堆设置
-Xms3550m 初始堆大小
-Xmx3550m 最大堆大小
-XX:NewSize1024 设置年轻代大小
-XX:NewRatio4 设置年轻代和年老代的比值.如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio8 设置年轻代中Eden区与一个Survivor区的比值默认为8
-XX:MaxPermSize256m 设置持久代大小收集器设置
-XX:UseSerialGC:设置串行收集器
-XX:UseParallelGC:设置并行收集器
-XX:UseParalledlOldGC:设置并行年老代收集器
-XX:UseConcMarkSweepGC:设置并发收集器垃圾回收统计信息
-XX:PrintGC
-XX:PrintGCDetails
-XX:PrintGCTimeStamps
-Xloggc:filename并行收集器设置
-XX:ParallelGCThreadsn:设置并行收集器收集时使用的CPU数.并行收集线程数.
-XX:MaxGCPauseMillisn:设置并行收集最大暂停时间
-XX:GCTimeRation:设置垃圾回收时间占程序运行时间的百分比.公式为1/(1n)并发收集器设置
-XX:CMSIncrementalMode:设置为增量模式.适用于单CPU情况.
-XX:ParallelGCThreadsn:设置并发收集器年轻代收集方式为并行收集时,使用的CPU数.并行收集线程数.JVM的堆配置过大的副作用有哪些? 答JVM的堆内存配置过大可能要面临的问题有
回收大块堆内存而导致的长时间的时间停顿。如果因为程序设计失误将大对象从磁盘读取到内存中可能会导致大对象在分配时直接进入老年代没有在 Minor GC 中被清理掉。这样会导致频繁的发生 Full GC给用户的体验是程序每个几分钟就停顿十几秒非常卡顿。
扩展JVM的堆配置过小的副作用有哪些
Minor GC 过于频繁 如果出现堆内存溢出 java.lang.OutOfMemoryError Java heap space该如何解决 答解决思路如下
首先需要拿到堆转储快照进行分析查看导致 OOM 的对象是否有必要存在并且分析清除是因为哪些对象导致了 OOM如果是内存泄漏导致 OOM可以查看泄露对象到GC Roots的引用链找到泄露对象在哪里被引用导致无法被回收如果不是内存泄漏那么说明内存中的对象都是存活的导致 OOM这时应该检查虚拟机的堆内存设置是否有向上调整的空间。并且检查是否存在对象生命周期过长、存储结构不合理的情况减少程序运行中的内存消耗。
扩展说明因为存储结构不合理导致堆内存溢出来自于《深入理解Java虚拟机第3版》
举例使用 HashMapLong, Long 存储大量的数据会导致浪费大量的空间因为 HashMap 的空间效率使用太低。
对于一个 HashMapLong, Long来说有效数据只有 Key、Value 的两个 long 型数据占 16字节long 数据被包装为 java.lang.Long 对象后就分别具有 8 字节的 Mark Word、8字节的 Klass 指针、8字节的 long 型数值。两个 Long 对象组成 Map.Entry 之后又多了 16 字节的对象头、8字节的 next 字段、4字节的 int 型的 hash 字段、4字节的空白填充为了对齐还有 HashMap 中对这个 Entry 的 8 字节的引用这样实际占用的内存为(Long(24byte) * 2) Entry(32byte) HashMap Ref(8byte)88byte空间效率仅仅为 16byte / 88byte 18%。 写代码时候有没有什么方式尽量减少Full GC的概率? 答
避免一次性加载大量数据加载到内存比如excel导入导出jdbc数据库查询避免大对象的代码处理业务链流程过长比如aop中获取到了对象参数大对象捕获到了导致对象生命周期变长了没及时释放。禁止使用system.gc方法避免在使用threalocal后未主动调用remove方法尽量避免大对象的使用以及频繁的创建和销毁。更要避免全局锁的竞争等。