当前位置: 首页 > news >正文

在开发过程中经常遇到 OOM(内存溢出)问题,如何解决?

3. SpringBoot 配置文件的加载顺序优先级是什么?如果目录同时存在 application.properties 和 application.yml,优先加载哪个?

  • 加载顺序优先级​(从高到低):

    1. 当前项目 classpath下的 /config目录下的配置文件。

    2. 当前项目 classpath根目录下的配置文件。

    3. 项目外部的 /config目录下的配置文件(如通过 --spring.config.location指定的外部配置路径)。

    4. 项目外部的根目录下的配置文件(同样可通过 --spring.config.location等指定)。

      (此外,命令行参数 --key=value的优先级是最高的,会在所有配置文件之后生效;还有环境变量、Profile 激活的配置等也会参与优先级判定,但上述是常见的文件类优先级逻辑。)

  • 同时存在 application.properties 和 application.yml 时​:

    SpringBoot ​优先加载 application.properties。因为 .properties格式的加载顺序在 .yml之前(.yml本质上是 YAML 格式,属于一种更简洁的结构化配置方式,但优先级低于 .properties)。

4. spring 的动态代理模式有几种?默认是哪种?如何切换?

Spring 动态代理主要分为两种技术实现思路:

  1. JDK 动态代理​:基于 Java 原生的 java.lang.reflect.ProxyInvocationHandler实现。要求被代理的目标类必须实现至少一个接口,代理类会继承 Proxy并实现目标接口,在运行时生成字节码。

  2. CGLIB 动态代理​:基于 ASM 字节码操作框架,在运行时对目标类的字节码进行增强,生成一个子类来作为代理类。这种方式不需要目标类实现接口,但会生成目标类的子类(所以如果目标类是 final类,就无法被 CGLIB 代理)。

  • 默认代理​:

    Spring 在早期版本中,默认会根据被代理对象是否有接口来选择代理方式:如果有接口,优先用 ​JDK 动态代理;如果没有接口,则用 CGLIB。

    从 Spring 4.0 之后,这个“自动选择”的逻辑有所调整,但大体上还是优先尝试 JDK 动态代理,若不满足(无接口)则 fallback 到 CGLIB。

  • 如何切换代理模式​:

    可以通过配置属性或者注解来指定使用哪种代理:

    • 全局配置(application.properties / application.yml)​​:

      # 强制使用 CGLIB 代理(即便目标类有接口,也走 CGLIB)
      spring.aop.proxy-target-class=true

      或者

      spring:aop:proxy-target-class: true  # true 表示强制 CGLIB;false 表示优先 JDK
    • 局部配置(@EnableAspectJAutoProxy 注解)​​:

      在开启 AOP 的 @Configuration类上,给 @EnableAspectJAutoProxy加上参数:

      @EnableAspectJAutoProxy(proxyTargetClass = true)  // true 表示强制 CGLIB

5. REST API 是无状态的吗,如何保障 API 的安全调用?

  • REST API 是否无状态​:

    REST(Representational State Transfer)架构风格本身要求 ​API 是无状态(Stateless)​​ 的。也就是说,服务端不保存客户端的状态信息,每次请求都应该包含理解该请求所需的全部信息(比如身份凭证、参数等),服务端仅根据本次请求的内容来做处理,不依赖于之前的请求上下文。

  • 如何保障 API 安全调用​?常见手段有以下几类:

    1. 身份认证(Authentication)​​:

      • 基于 Token​:如 JWT(JSON Web Token)。客户端登录成功后,服务端生成包含用户信息的 JWT 并返回,后续客户端每次请求都在请求头(如 Authorization: Bearer <token>)中携带该 Token,服务端验证 Token 合法性与有效性即可完成认证。

      • OAuth2​:适用于第三方授权场景,通过授权码模式、隐式授权模式、密码模式、客户端模式等,让资源所有者(用户)授权第三方应用访问受保护资源。

      • HTTP Basic Auth​:将用户名和密码进行 Base64 编码后放在请求头的 Authorization字段,服务端解码后验证。不过这种方式明文传输风险较高,一般要配合 HTTPS 使用。

    2. 授权(Authorization)​​:

      认证通过后,还需判断该用户是否有权限访问某个 API 或操作某个资源。常见做法是基于角色的访问控制(RBAC)、基于资源的访问控制(RBAC 扩展或 ABAC 等),在服务端代码或借助框架(如 Spring Security)来做权限校验。

    3. 数据加密与完整性​:

      • HTTPS​:强制使用 HTTPS 协议,对请求和响应进行 TLS 加密,防止中间人窃听、篡改数据。

      • 签名(Signature)​​:对请求参数按一定规则排序后,用密钥生成签名,服务端收到请求后同样生成签名做比对,确保请求在传输过程中没有被篡改。常用于对安全性要求极高的场景(如金融类 API)。

    4. 防重放攻击​:

      给每个请求加上唯一标识(如时间戳 + 随机数)或者使用 nonce(一次性随机数),服务端记录已使用的标识,拒绝重复的请求,避免攻击者截获请求后重复发送来达到非法目的。

    5. 输入校验与过滤​:

      对客户端传入的参数进行严格的格式、长度、范围等校验,防止 SQL 注入、XSS(跨站脚本)等攻击。可以使用框架自带的校验注解(如 Spring 的 @Valid结合 JSR-303 规范),也可以手动编写校验逻辑。

6. 在开发过程中经常遇到 OOM(内存溢出)问题,如何解决?

OOM(Out Of Memory)指 Java 虚拟机在分配对象时,没有足够的内存空间,抛出 java.lang.OutOfMemoryError异常。常见原因与解决思路如下:

1. 先定位 OOM 场景与堆栈信息
  • 获取内存快照​:

    使用 JDK 自带的 jmap命令、可视化工具(如 Eclipse MAT、VisualVM、YourKit 等)抓取堆转储文件(.hprof)。例如:

    jmap -dump:format=b,file=heap.hprof <pid>

    然后在工具里分析内存占用大的对象、引用链,看是哪些类实例过多、占用内存异常。

  • 分析 OOM 报错信息​:

    OOM 的具体子类(如 java.lang.OutOfMemoryError: Java heap spacejava.lang.OutOfMemoryError: Metaspacejava.lang.OutOfMemoryError: GC overhead limit exceeded等)能帮我们缩小问题范围。

2. 针对不同场景的常见原因与解决
  • Java Heap Space 溢出(堆内存不足)​​:

    • 原因​:对象太多且无法被 GC 回收(存在内存泄漏),或者对象本身就很大(如加载了大文件到内存、超大集合)。

    • 解决​:

      1. 检查是否存在内存泄漏​:看是否有对象被意外地长期引用(比如静态集合里一直 add 对象但没 remove,或者单例对象持有大对象引用不释放等)。借助内存分析工具找到泄漏点,修正代码逻辑。

      2. 调整堆内存大小:如果业务确实需要较大堆空间,可以适当增大 -Xmx(最大堆)和 -Xms(初始堆)参数,但要结合服务器资源合理设置。

      3. 优化对象创建与使用:减少不必要的对象创建(比如用对象池复用对象);对大集合做分页、分批处理,避免一次性加载过多数据到内存。

  • Metaspace 溢出​:

    • 原因​:Metaspace 是存放类元数据的地方(JDK 8+ 取代了永久代 PermGen)。如果应用动态生成大量类(如频繁使用 CGLIB 代理、动态字节码技术,或者框架内部生成过多代理类),且没有及时卸载,就会导致 Metaspace 耗尽。

    • 解决​:

      1. 减少动态类的生成:检查是否有不必要的动态代理、字节码增强操作;对框架配置做优化(比如减少 AOP 切面过多、减少不必要的自动代理)。

      2. 调整 Metaspace 参数:增大 -XX:MaxMetaspaceSize(最大元空间大小),并配合 -XX:MetaspaceSize(初始元空间大小)设置合理阈值;同时关注 -XX:+UseCompressedClassPointers等压缩指针参数对 Metaspace 的影响。

  • GC Overhead Limit Exceeded​:

    • 原因​:GC 回收时间占比过高(比如连续多次 GC 都只能回收很少内存),JVM 认为继续 GC 没意义,直接抛出 OOM。本质还是堆内存不足或存在大量无法回收的对象。

    • 解决​:

      1. 先排查是不是 Heap Space 或 Metaspace 的问题,参考上面两类场景的处理方式。

      2. 如果业务场景允许,可以适当调整 -XX:-UseGCOverheadLimit关闭这个检查(不推荐,属于治标不治本,最好还是先找内存问题根源)。

  • Direct Memory 溢出(NIO 直接内存)​​:

    • 原因​:Java NIO 中通过 java.nio.DirectByteBuffer分配的直接内存(不受 JVM 堆管理,由操作系统本地内存分配),如果分配过多且没释放,会导致 Direct Memory 不足。常见于大量使用 Netty 等基于 NIO 的网络框架,或者手动频繁分配直接内存的场景。

    • 解决​:

      1. 检查直接内存的分配与释放逻辑,确保不再使用的 DirectByteBuffer能被正确回收(可以通过 -XX:MaxDirectMemorySize限制直接内存大小)。

      2. 调整 JVM 参数,比如 -XX:MaxDirectMemorySize=256m(限制最大直接内存为 256MB),并监控实际使用情况。

  • Stack Overflow(栈溢出,虽不属于 Heap OOM,但也是常见内存问题)​​:

    • 原因​:线程请求的栈深度超过了 JVM 所允许的最大深度(比如递归调用没有终止条件)。

    • 解决​:

      1. 检查递归、循环等逻辑,确保有正确的终止条件。

      2. 调整栈大小参数 -Xss(如 -Xss2m表示每个线程栈大小为 2MB),但要注意栈太大可能导致线程数减少,需权衡。

3. 通用优化与监控思路
  • 代码层面​:做好对象生命周期管理、减少不必要的对象创建、合理使用集合类(避免扩容带来的额外开销)、及时关闭资源(IO 流、数据库连接等)。

  • JVM 调优​:根据应用特点调整堆、Metaspace、Direct Memory 等参数;选择合适的 GC 算法(如 G1、ZGC 等低延迟 GC,适合对停顿敏感的业务)。

  • 监控与告警​:在生产环境部署 APM 工具(如 Prometheus + Grafana、SkyWalking 等),对内存使用率、GC 频率与耗时等指标做实时监控,出现异常时及时告警,便于快速定位问题。

http://www.dtcms.com/a/360600.html

相关文章:

  • __getitem__()方法的神奇
  • 【LeetCode修行之路】算法的时间和空间复杂度分析
  • 2000w 的数据量,mysql要进行几次IO操作,为什么
  • GEE 实战:Landsat 5 月度 NDVI 数据插值填补(以 8 月为例)_后附完整代码
  • sting模拟实现
  • 前后端联合实现多个文件上传
  • FastAPI 教程:构建高性能异步 API 服务
  • 石化设备健康管理平台:工业智能化转型的关键使能技术​
  • std::thread详解
  • Spring Boot单体项目整合Nacos
  • C++17 折叠表达式(Fold Expressions)详解
  • ConcurrentHashMap在扩容的过程中又有新的数据写入是怎么处理的
  • 《Bishop PRML》10.1 (3) 理解VAE reconstruction loss
  • Redis 中的 Bitmap 与 Bitfield 及 Java 操作实践
  • python如何下载svg图片
  • 【Proteus仿真】数码管控制系列仿真——单个数码管控制/多数码管控制
  • leetcode 260 只出现一次的数字III
  • 你的数据是如何被保护的?
  • Linux系统的进程管理
  • vue3+vite+ts 发布npm 组件包
  • 查看所有装在c盘软件的方法
  • [知识点记录]SQLite 数据库和MySQL 数据库有什么区别?
  • DuckDB 内嵌分析:ABP 的「本地 OL盘快照」
  • 福彩双色球第2025100期号码推荐
  • 福彩双色球第2025100期数据统计
  • 吴恩达机器学习作业十一:异常检测
  • Docker 容器(二)
  • 机器视觉学习-day15-图像轮廓特征查找
  • Wi-Fi技术——OSI模型
  • 深度学习量化双雄:PTQ 与 QAT 的技术剖析与实战