# Java内存管理问题

# 问题一:集合类内存泄漏

# 问题描述

  • List、Map等集合中的对象不再使用时未及时remove
  • 自定义缓存未设置过期时间和清理机制
  • 大对象的局部变量未及时置null

# 解决方案

  1. 使用WeakHashMap实现缓存
WeakHashMap<String, Object> cache = new WeakHashMap<>();
  1. 使用Guava Cache设置过期时间
Cache<String, Object> cache = CacheBuilder.newBuilder()
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build();
  1. 最佳实践
  • 及时清理不再使用的元素
  • 合理设置初始容量
  • 使用合适的集合类型
  • 注意对象的equals和hashCode实现

# 问题二:资源未释放

# 问题描述

  • 数据库连接使用后未关闭
  • 文件流未正确关闭
  • Socket连接未释放
  • 网络连接未断开

# 解决方案

  1. 使用try-with-resources自动关闭资源
try (FileInputStream fis = new FileInputStream(file)) {
    // 使用文件流
} catch (IOException e) {
    // 异常处理
}
  1. 最佳实践
  • 使用try-with-resources语句
  • 实现AutoCloseable接口
  • 在finally块中确保资源释放
  • 使用连接池管理资源

# 问题三:ThreadLocal使用不当

# 问题描述

  • 线程池中的线程重复使用导致ThreadLocal变量未及时清理
  • 子线程继承了父线程的ThreadLocal变量但未清理
  • 使用static ThreadLocal但未注意及时remove

# 解决方案

  1. 规范使用ThreadLocal
public class ThreadLocalExample {
    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    public void process() {
        try {
            threadLocal.set("some value");
            // 业务处理
        } finally {
            threadLocal.remove(); // 确保清理ThreadLocal
        }
    }
}
  1. 最佳实践
  • 避免static ThreadLocal的使用
  • 在finally块中确保remove
  • 使用ThreadLocal.withInitial()设置初始值
  • 考虑使用TransmittableThreadLocal

# 问题四:监听器和回调未注销

# 问题描述

  • 事件监听器在组件销毁时未移除
  • 自定义观察者模式中的观察者对象未及时注销
  • 注册的回调未及时解除

# 解决方案

  1. 使用弱引用存储监听器
WeakReference<EventListener> weakListener = 
    new WeakReference<>(new EventListener());
  1. 最佳实践
  • 在组件销毁时注销监听器
  • 使用弱引用存储监听器
  • 避免循环引用
  • 实现取消注册机制