首页 > 编程语言 >阿里面试:Java开发中,应如何避免OOM

阿里面试:Java开发中,应如何避免OOM

时间:2024-02-21 17:24:48浏览次数:32  
标签:Java OOM 面试 obj 对象 内存 使用 new

Java内存管理:避免OOM的10个实用小技巧

引言

在Java开发中,OutOfMemoryError(OOM)错误一直是令开发者头疼的问题,也是Java面试中出现核心频率很高的问题。
那么我们究竟怎么样才能够有效正确的管理内存,日常开发中究竟要注意哪些核心技巧来避免OOM错误。
本文将带大家一起学习10个避免OOM的实用小技巧,让大家在工作中能够有的放矢,避免OOM错误的飞来横祸。

正文

1、 合理配置JVM内存参数
应用上线前,设置合理的JVM启动参数是避免OOM的第一步。
通过调整堆内存、栈内存和Metaspace的大小,可以有效地管理内存资源。
以4G内存为例,应用上线时可以参考如下配置:

// 示例:设置JVM的启动参数
// -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进行字符串操作。

// 使用原始数据类型代替包装类
int i = 10;

// 使用StringBuilder进行字符串拼接
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
String result = sb.toString();`

3、 对象池技术
对于频繁创建和销毁的对象,可以考虑使用对象池技术,以减少GC的压力。

// 使用Commons Pool2实现对象池
// 定义一个简单的对象池工厂
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);
}```


**4、** **优化数据结构选择**
根据应用场景合理选择数据结构,例如,在频繁读取操作中使用ArrayList,在频繁插入删除操作中使用LinkedList。

```java
// 在频繁读取操作中使用ArrayList
List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");
String element = arrayList.get(0);

// 在频繁插入删除操作中使用LinkedList
List<String> linkedList = new LinkedList<>();
linkedList.add("Java");
linkedList.add("Python");
linkedList.remove(0);

5、 避免创建不必要的对象
尽量复用已有对象,避免无谓的对象创建,特别是在循环或频繁调用的方法中。

// 避免在循环中创建对象
String result = "";
for(int i = 0; i < 100; i++) {
    // 错误示范:在循环体内创建StringBuilder对象
    // 正确做法是将StringBuilder的创建放到循环体外
    StringBuilder sb = new StringBuilder(result);
    sb.append(i);
    result = sb.toString();
}

6、 及时释放不再使用的对象
确保不再使用的对象能够被GC及时回收,例如,将对象引用设置为null,关闭流等。

// 将对象引用设置为null
Object obj = new Object();
// 使用对象...
obj = null; // 明确标记obj不再使用

// 关闭流
FileInputStream fis = null;
try {
    fis = new FileInputStream("test.txt");
    // 使用流...
} finally {
    if(fis != null) {
        fis.close();
    }
}

7、 使用软引用和弱引用管理内存
对于可回收的对象,使用软引用(SoftReference)或弱引用(WeakReference),以便在JVM内存不足时能被回收。

// 使用软引用
SoftReference<Object> softRef = new SoftReference<>(new Object());
// 使用弱引用
WeakReference<Object> weakRef = new WeakReference<>(new Object());

8、 合理使用缓存
合理设计缓存策略,避免缓存占用过多内存。可以使用第三方缓存库如Ehcache,Guava Cache等,并设置合理的过期策略。

// 使用Guava Cache
Cache<String, Object> cache = CacheBuilder.newBuilder()
        .maximumSize(1000)
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .build();
// 向缓存中添加对象
cache.put("key", new Object());
// 从缓存中获取对象
Object obj = cache.getIfPresent("key");

9、 监控和分析内存使用
使用JVM提供的工具(如jvisualvm, jconsole)监控和分析应用的内存使用情况,及时发现并解决内存问题。

10、 优化GC策略
根据应用的实际情况,调整和优化GC策略,减少GC的执行时间,提升系统的性能。

本文总结

监控和分析内存使用
使用JVM提供的工具(如jvisualvm, jconsole)监控和分析应用的内存使用情况,及时发现并解决内存问题。

10、 优化GC策略
根据应用的实际情况,调整和优化GC策略,减少GC的执行时间,提升系统的性能。

本文总结

避免OOM错误并非难事,关键在于对Java内存管理有深入的理解和正确的实践。通过以上10个实用小技巧的应用,可以有效地管理和优化Java应用的内存使用,避免内存溢出的问题。务必记得,持续的监控、分析和优化是保持应用稳定运行的关键。

最后说一句(求关注,求赞,别白嫖我)

最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难。

这是大佬写的, 7701页的BAT大佬写的刷题笔记,让我offer拿到手软

本文,已收录于,我的技术网站 aijiangsir.com,有大厂完整面经,工作技术,架构师成长之路,等经验分享

求一键三连:点赞、分享、收藏

点赞对我真的非常重要!在线求赞,加个关注我会非常感激!

标签:Java,OOM,面试,obj,对象,内存,使用,new
From: https://www.cnblogs.com/jiang-xiao-bei/p/18025718

相关文章

  • 面试题随笔-2月21日
    Java–异常/Exception–try/catch/finally的return顺序try块执行·try中的代码会先执行·try如果没用抛出异常则正常执行,如果存在return则会返回方法调用的地方catch块执行·如果try块中的代码抛出一个异常,与catch字句匹配的异常类型将被捕获并执行相应的cat......
  • 04-JavaScript介绍
      注意:JS是脚本语言,不需要经过编译,直接经过浏览器的解释就可以运行了。而Java语言需要先编译成class文件,再通过虚拟机进行运行。  <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>JS-引入方式</title></head><body>......
  • Java人力资源管理系统源码(含数据库)-springboot+vue+mysql
    EHR人力资源管理系统是一种利用现代技术,如云计算、大数据等,来实现企业人力资源信息电子化、流程自动化的系统。它覆盖了人力资源管理的各个方面,从招聘、考勤、绩效到薪酬、社保公积金等,为企业提供一站式的解决方案。​1.招聘管理:-职位发布:系统支持在线发布职位信息,吸引候选人......
  • java常量变量
    标识符标识符:给类,接口,方法,变量等起名时使用的字符序列规则:1.英文大小写构成可以有数字,下划线_和$存在规范1.不能以数字开头2.不能是Java中的关键字3.区分大小写4.要见名知意5.不要出现除了下划线_和$以外的特殊字符包(其实就是文件夹,用于解决相同类名问题)由英文小写......
  • Java导入功能实现
    今天记录一下Java实现导入数据到数据,导入失败显示如下,会告诉你哪里出错了。controller代码实现@Operation(summary="导入工单")@PostMapping("/importOrderData")publicBaseResponse<String>importOrderData(@RequestParam@Parameter(name="excelFile",......
  • 《Effective Java》阅读笔记-第九章
    EffectiveJava阅读笔记第九章通用编程第57条将局部变量的作用域最小化将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能。将局部变量的作用域最小化,最好的办法就是在第一次使用变量的地方声明它。几乎每一个局部变量都应该进行初始化。第5......
  • 《Effective Java》阅读笔记-第八章
    EffectiveJava阅读笔记第八章方法第49条检查参数的有效性基于“发生错误后应尽快检测出错误”这一通用原则,应对方法的参数进行检查。Java7中增加了Objects.requireNonNull方法,可以很方便的对参数进行null检查并抛出异常:publicvoidsomeMethod(Stringargs){ar......
  • 《Effective Java》阅读笔记-第十一章
    EffectiveJava阅读笔记第十一章并发第78条同步访问共享的可变数据多线程访问变量时,需要进行同步,否则就会产生并发问题。同步代码块、加锁等或者直接不共享变量,也就是将可变数据限制在单个线程内。ThreadLocal这种第79条避免过度同步为了避免活性失败和安全性失败......
  • 《Effective Java》阅读笔记-第十章
    EffectiveJava阅读笔记第十章异常第69条只针对异常的情况才使用异常说白了就是不要吧你的业务逻辑用异常来写。举个反例比如用抛出异常来遍历一个数组:try{inti=0;while(true){range[i++].doSomething();}}catch(ArrayIndexOutOfBoun......
  • 《Effective Java》阅读笔记-第十二章
    EffectiveJava阅读笔记第十二章序列化第85条其他方法优先于Java本身的序列化Java本身的序列化漏洞过多,很容易被攻击。避免被序列化攻击的最好方式就是不要反序列化任何字节流,并且新的系统中没有任何理由使用Java本身的序列化。JSON和Protobuf是两种优秀的序列化......