示例代码
java复制public class ObjectPool<T> { private final Queue<T> pool; private final Supplier<T> objectSupplier; public ObjectPool(int capacity, Supplier<T> objectSupplier) { this.pool = new ArrayDeque<>(capacity); this.objectSupplier = objectSupplier; } public T borrowObject() { return pool.poll(); } public void returnObject(T object) { pool.offer(object); } public T createObject() { return objectSupplier.get(); } } public class MyObject { // 对象的属性和方法 } public class Main { public static void main(String[] args) { ObjectPool<MyObject> pool = new ObjectPool<>(10, MyObject::new); MyObject obj1 = pool.borrowObject(); if (obj1 == null) { obj1 = pool.createObject(); } // 使用obj1 pool.returnObject(obj1); } }
(二)使用软引用和弱引用
软引用和弱引用是Java中的两种引用类型,用于管理对象的生命周期,避免内存泄漏。
软引用:在内存不足时,JVM会自动回收软引用指向的对象。
java复制public class SoftReferenceExample { public static void main(String[] args) { SoftReference<byte[]> softRef = new SoftReference<>(new byte[1024 * 1024 * 10]); // 10MB // 模拟内存不足 byte[] bytes = new byte[1024 * 1024 * 100]; // 100MB if (softRef.get() == null) { System.out.println("Soft reference object has been collected"); } else { System.out.println("Soft reference object is still alive"); } } }
弱引用:在下一次GC时,JVM会自动回收弱引用指向的对象。
java复制public class WeakReferenceExample { public static void main(String[] args) { WeakReference<byte[]> weakRef = new WeakReference<>(new byte[1024 * 1024 * 10]); // 10MB // 模拟GC System.gc(); if (weakRef.get() == null) { System.out.println("Weak reference object has been collected"); } else { System.out.println("Weak reference object is still alive"); } } }
public class Example {
private SomeComponent component;
private SomeListener listener;
public Example(SomeComponent component) {
this.component = component;
listener = new SomeListener();
component.addListener(listener);
}
}
public class Example {
private static ExecutorService executor = Executors.newCachedThreadPool();
public void execute(Runnable task) {
executor.execute(task);
}
}
public class Example {
private static List<Object> list = new ArrayList<>();
public void add(Object obj) {
list.add(obj);
}
}
(二)监听器和回调
注册了监听器或回调但未及时注销,会导致监听器或回调所引用的对象无法被垃圾回收,引发内存泄漏。
java复制
代码语言:javascript
代码运行次数:0
复制
public class Example {
private SomeComponent component;
private SomeListener listener;
public Example(SomeComponent component) {
this.component = component;
listener = new SomeListener();
component.addListener(listener);
}
public void destroy() {
component.removeListener(listener);
}
}
public class Example {
private static ThreadLocal<Object> threadLocal = new ThreadLocal<>();
public void set(Object obj) {
threadLocal.set(obj);
}
public void remove() {
threadLocal.remove();
}
}
public class Example {
public void readFile(String filePath) {
FileInputStream fis = new FileInputStream(filePath);
try {
// 读取文件
} finally {
fis.close();
}
}
}
(六)内部类和匿名类的静态引用
内部类和匿名类的静态引用会持有外部类的引用,导致外部类对象无法被垃圾回收,引发内存泄漏。
java复制
代码语言:javascript
代码运行次数:0
复制
public class Example {
private static class InnerClass {
// 内部类的静态引用
}
private static InnerClass inner = new InnerClass();
}
静态变量的生命周期与类的生命周期相同,如果静态变量引用了大量对象,会导致这些对象无法被垃圾回收。要合理使用静态变量,避免静态变量引用不必要的对象。
java复制public class Example { private static List<Object> staticList = new ArrayList<>(); public void add(Object obj) { staticList.add(obj); } }
在这个例子中,staticList会一直引用添加到其中的对象,导致这些对象无法被垃圾回收。可以考虑将staticList改为非静态变量,或者在不需要时清空staticList。
避免不必要的监听器注册
在使用监听器时,如果注册了监听器但未及时注销,会导致监听器所引用的对象无法被垃圾回收。要在不再需要监听器时,及时注销监听器。
java复制public class Example { private SomeComponent component; private SomeListener listener; public Example(SomeComponent component) { this.component = component; listener = new SomeListener(); component.addListener(listener); } public void destroy() { component.removeListener(listener); } }
合理使用缓存
缓存机制如果不合理,会导致缓存对象无法被垃圾回收,引发内存泄漏。可以使用弱引用来管理缓存对象,或者定期清理缓存。
java复制public class CacheExample { private Map<String, WeakReference<Object>> cache = new HashMap<>(); public void put(String key, Object value) { cache.put(key, new WeakReference<>(value)); } public Object get(String key) { WeakReference<Object> ref = cache.get(key); return ref == null ? null : ref.get(); } public void clearCache() { cache.clear(); } }
避免使用静态集合类
静态集合类的生命周期与类的生命周期相同,如果静态集合类中添加了大量对象,这些对象会一直被集合引用,无法被垃圾回收。可以考虑将静态集合类改为非静态变量,或者在不需要时清空集合。
java复制public class Example { private List<Object> list = new ArrayList<>(); public void add(Object obj) { list.add(obj); } public void clearList() { list.clear(); } }
(二)设计层面的优化
使用弱引用和软引用
对于一些可缓存的对象,可以使用弱引用或软引用来管理。弱引用的对象在下一次GC时会被回收,软引用的对象在内存不足时会被回收。
java复制public class CacheExample { private Map<String, SoftReference<Object>> cache = new HashMap<>(); public void put(String key, Object value) { cache.put(key, new SoftReference<>(value)); } public Object get(String key) { SoftReference<Object> ref = cache.get(key); return ref == null ? null : ref.get(); } public void clearCache() { cache.clear(); } }
合理使用单例模式
单例模式的实例会一直存在于内存中,如果单例对象引用了大量其他对象,会导致这些对象无法被垃圾回收。要合理设计单例模式,避免单例对象引用不必要的对象。
java复制public class Singleton { private static volatile Singleton instance; private List<Object> list = new ArrayList<>(); private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } public void add(Object obj) { list.add(obj); } public void clearList() { list.clear(); } }
使用资源池
资源池可以重用对象,减少对象的创建和销毁次数,提高性能。例如,可以使用数据库连接池、线程池等。
java复制public class ConnectionPool { private Queue<Connection> pool = new LinkedList<>(); public ConnectionPool(int capacity) { for (int i = 0; i < capacity; i++) { pool.add(createConnection()); } } private Connection createConnection() { // 创建数据库连接 return new Connection(); } public Connection borrowConnection() { return pool.poll(); } public void returnConnection(Connection connection) { pool.offer(connection); } }
public class Example {
private static List<Object> list = new ArrayList<>();
public void add(Object obj) {
list.add(obj);
}
}
(二)使用非静态集合类
可以考虑将静态集合类改为非静态变量,或者在不需要时清空集合。
java复制
代码语言:javascript
代码运行次数:0
复制
public class Example {
private List<Object> list = new ArrayList<>();
public void add(Object obj) {
list.add(obj);
}
public void clearList() {
list.clear();
}
}
(三)使用弱引用管理集合中的对象
可以使用弱引用来管理集合中的对象,避免内存泄漏。
java复制
代码语言:javascript
代码运行次数:0
复制
public class Example {
private List<WeakReference<Object>> list = new ArrayList<>();
public void add(Object obj) {
list.add(new WeakReference<>(obj));
}
public void clearList() {
list.clear();
}
}
(四)定期清理集合
可以定期清理集合中的对象,避免内存泄漏。
java复制
代码语言:javascript
代码运行次数:0
复制
public class Example {
private List<Object> list = new ArrayList<>();
public void add(Object obj) {
list.add(obj);
}
public void clearList() {
list.clear();
}
public void cleanup() {
list.removeIf(Objects::isNull);
}
}
(五)使用局部变量
如果集合只在某个方法或某个作用域内使用,可以使用局部变量,避免使用静态集合类。
java复制
代码语言:javascript
代码运行次数:0
复制
public class Example {
public void process() {
List<Object> list = new ArrayList<>();
// 使用list
}
}
java复制public class Example { private List<WeakReference<Object>> list = new ArrayList<>(); public void add(Object obj) { list.add(new WeakReference<>(obj)); } public void clearList() { list.removeIf(WeakReference::get).isNull()); } }
定期清理集合:
可以定期清理集合中的对象,避免内存泄漏。
java复制public class Example { private List<Object> list = new ArrayList<>(); public void add(Object obj) { list.add(obj); } public void clearList() { list.clear(); } public void cleanup() { list.removeIf(Objects::isNull); } }
使用局部变量:
如果集合只在某个方法或某个作用域内使用,可以使用局部变量,避免使用静态集合类。
java复制public class Example { public void process() { List<Object> list = new ArrayList<>(); // 使用list } }
java复制public class Example { private static WeakReference<List<Object>> staticList = new WeakReference<>(new ArrayList<>()); public void add(Object obj) { List<Object> list = staticList.get(); if (list != null) { list.add(obj); } } }
定期清理静态变量:
可以定期清理静态变量中的对象,避免内存泄漏。
java复制public class Example { private static List<Object> staticList = new ArrayList<>(); public void add(Object obj) { staticList.add(obj); } public void clearList() { staticList.clear(); } }