引言
在 Java 开发中,OutOfMemoryError(OOM)错误一直是令开发者头疼的问题,也是 Java 面试中出现频率很高的问题。
那么我们究竟怎么样才能在开发中避免 OOM 错误?
本文将带大家一起学习 6个避免 OOM 的编码技巧!
正文
1.合理配置JVN内存参数
合理设置JVM参数是有效管理内存资源、避免OOM的第一步。
以下是4G内存的参考配置:
-Xms1024m 设置初始堆大小为1024MB
-Xmx2048m 设置最大堆大小为2048MB
-XX:NewSize=512m 设置新生代大小为512MB
-XX:MaxNewSize=1024m 设置新生代最大大小为1024MB
-XX:MetaspaceSize=256m 设置Metaspace的初始空间大小为256MB
-XX:MaxMetaspaceSize=512m 设置Metaspace的最大空间大小为512MB
2.尽量使用轻量级对象
例如,使用原始数据类型代替包装类
;使用 StringBuffer/StringBuilder 代替 String
进行字符串操作。
3.频繁使用对象循环引用
对象池技术
:线程池使用后的对象能够回收,循环使用。
// 定义一个简单的对象池工厂
public class MyObjectPoolFactory extends BasePooledObjectFactory<MyObject> {
@Override
public MyObject create() throws Exception {
return new MyObject();
}
@Override
public PooledObject<MyObject> wrap(MyObject obj) {
return new DefaultPooledObject<>(obj);
}
}
// 使用对象池
ObjectPool<MyObject> pool = new GenericObjectPool<>(new MyObjectPoolFactory());
MyObject obj = null;
try {
obj = pool.borrowObject();
// 使用对象...
} finally {
pool.returnObject(obj);
}
- 技术框架Bean对象业务域的选择
例如:spring框架可以通过配置文件指定scope为singletonBean(单例模式:默认)还是prototypeBean(多例模式)。
单例模式
- 优势:
- 节省资源:由于只创建一个实例,减少了内存开销。
- 共享实例:在应用中所有对该Bean的请求都获得相同的对象实例,便于进行操作和管理。
- 场景:适用于那些不需要维护任何状态信息的共享组件。
多例模式
- 优势:
- 独立性:每个实例都是独立的,避免了因共享实例而引起的潜在冲突和依赖。
- 特定状态:适合那些有状态的Bean,保证每个状态都是新的,不会被其他引用影响。
- 场景:适用于每个用户或操作都需要一个独立实例的情况。
4.及时释放不再使用对象
确保对象及时被GC,可以将对象设置为null11
,关闭流
等。
// 1.将对象引用设置为null
Object obj = new Object();
// ...
// 明确标记obj不再使用
obj = null;
// 2.关闭流
FileInputStream is = null;
try {
is = new FileInputStream("test.txt");
// ...
} finally {
if(is != null) {
// 关闭流
is.close();
}
}
5.使用软引用和弱引用(特别不建议
)
1.软引用:是一种相对强引用弱化了一些的引用关系。当一个对象只有软引用时,在JVM内存不足的情况下,垃圾回收器会考虑回收这些对象以释放内存。因此,软引用适合实现内存敏感的缓存。
SoftReference<Object> softRef = new SoftReference<>(new Object());
2.弱引用:比软引用更弱,当一个对象只有弱引用时,这种对象在下一次垃圾回收时会被回收,不管当前内存空间足够与否。弱引用通常用于实现对对象的非持久引用,如元数据、监听器和解决循环依赖等。
WeakReference<Object> weakRef = new WeakReference<>(new Object());
6.合理使用缓存
合理设置缓存及过期策略能够避免占用过多的内存。
总结
避免OOM并非难事,关键在于对内存管理有深入的了解,以及有良好的编码习惯。
除此之外,持续的监控、分析和优化也是保持应用稳定运行的关键。