要搞定内存管理,首先得清楚JVM的内存“疆域”。JVM内存主要分为线程私有和线程共享两大类:
StackOverflowError)、本地方法栈(支持Native方法调用);内存泄漏是Java应用最常见的“隐形杀手”,典型场景包括:
List/Map缓存大量对象(如商品详情、临时数据),会导致这些对象无法被GC回收。排查时可通过jmap -histo:live <pid>查看对象实例数,用MAT分析引用链(重点关注静态变量持有的对象)。DisposableBean接口或使用@PreDestroy注解,在Bean销毁时注销监听器。HashMap缓存)会占用大量内存。建议使用带过期策略的缓存框架(如Guava的LoadingCache、Caffeine),设置最大大小(maximumSize)和过期时间(expireAfterAccess)。java.lang.OutOfMemoryError: Java heap space,通常因对象创建过多(如循环内创建大对象、缓存未清理)。解决方法是调整堆大小(-Xms初始堆、-Xmx最大堆,建议设为相同值避免频繁扩容),优化对象创建(如重用StringBuilder、使用对象池)。java.lang.OutOfMemoryError: Metaspace,因动态类加载过多(如反射生成代理类、加载大量jar包)。解决方法是调整元空间大小(-XX:MetaspaceSize初始大小、-XX:MaxMetaspaceSize最大大小,默认无限制),减少动态类生成。StringBuilder,应将其移到循环外并重置长度(sb.setLength(0)),减少内存分配次数。Integer、Double)会创建对象,基本类型(int、double)直接存储值,减少内存开销(如List<Integer>改为int[])。SimpleDateFormat(线程不安全,可使用ThreadLocal重用),避免频繁创建和销毁。HashMap vs LinkedList:HashMap查找时间复杂度为O(1),适合快速检索;LinkedList插入/删除时间复杂度为O(1),适合频繁增删。海量数据时,HashMap的内存占用更小。EnumSet(枚举集合)、EnumMap(枚举键映射)比通用集合(HashSet、HashMap)更节省内存(如EnumSet.of(Color.RED, Color.GREEN))。-XX:+UseG1GC,默认停顿目标200ms)、ZGC(-XX:+UseZGC,亚毫秒级停顿)、Shenandoah(-XX:+UseShenandoahGC,低停顿),适合互联网应用。-XX:+UseParallelGC,多线程吞吐量优先)、Parallel Old GC(-XX:+UseParallelOldGC,老年代并行回收),适合批处理任务。-Xms/-Xmx(堆大小)、-XX:NewRatio(新生代/老年代比例,默认2,即新生代占1/3)、-XX:SurvivorRatio(Eden/Survivor比例,默认8,即Eden占80%)。jstat -gcutil <pid> 1000 5,每秒输出一次GC统计,共5次),查看S0U(Survivor 0使用率)、EU(Eden使用率)、OU(老年代使用率),判断是否内存泄漏。jcmd <pid> GC.class_histogram,类似jmap -histo),查看对象实例数最多的类,定位内存占用高的对象。jmap -dump:live,format=b,file=heapdump.hprof <pid>,live参数只导出存活对象),用MAT(Eclipse Memory Analyzer)或VisualVM分析,查看对象引用链(如静态变量持有的对象)。dashboard查看内存概况,trace追踪方法调用链路),在线排查内存问题,无需重启应用。try-with-resources(try (FileInputStream fis = new FileInputStream("file.txt")))自动关闭文件、数据库连接等资源,避免资源泄漏。WeakReference(内存不足时回收)、SoftReference(GC时回收),避免对象长期驻留内存。通过以上实战技巧,能有效提升Java应用的内存使用效率,减少内存泄漏和OOM问题的发生。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。