直接内存泄漏与JVM源码分析

直接内存(堆外内存)

在这里插入图片描述

直接内存(堆外内存)指的是 Java 应用程序通过直接方式从操作系统中申请的内存。这个差别与之前的堆、栈、方法区,那些内存都是经过了虚拟化。所以严格来说,这里是指直接内存。

直接内存有哪些?

 使用了 Java 的 Unsafe 类,做了一些本地内存的操作;
 Netty 的直接内存(Direct Memory),底层会调用操作系统的 malloc 函数。
JNI 或者 JNA 程序,直接操纵了本地内存,比如一些加密库;
JNI 是 Java Native Interface 的缩写,通过使用 Java 本地接口书写程序,可以确保代码在不同的平台上方便移植。
JNA(Java Native Access )提供一组 Java 工具类用于在运行期间动态访问系统本地库(native library:如 Window 的 dll)而不需要编写任何 Native/JNI 代码。

下面通过代码来具体分析

  1. Unsafe 类,-XX:MaxDirectMemorySize 参数的大小限制对这种是无效的
/**
 * @author
 * 参数无效:-XX:MaxDirectMemorySize=10m
 */
public class UnsafeDemo {
   
    public static final int _1MB = 1024 * 1024;

    public static void main(String[] args) throws Exception {
   
        Field field = Unsafe.class.getDeclaredField("theUnsafe");
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        long addr = unsafe.allocateMemory(100*_1MB);
    }
}
2.
import java.nio.ByteBuffer;

/**
 * @author
 * VM Args:-XX:MaxDirectMemorySize=100m
 * 限制最大直接内存大小100m
 * -XX:MaxDirectMemorySize=128m
 * -Xmx128m
 * -Xmx135m -Xmn100m -XX:SurvivorRatio=8
 * -Xmx138m -Xmn100m -XX:SurvivorRatio=8
 */
public class ByteBufferDemo {
   
    static ByteBuffer bb;
    public static void main(String[] args) throws Exception {
   
        //直接分配128M的直接内存
        bb = ByteBuffer.allocateDirect(128*1024*1024);
    }
}

在这里插入图片描述
在这里插入图片描述
3.在这里插入图片描述
如果这样配置参数,发现不会发生OOM。这里思考一下为什么138m的时候就不会发生oom了呢?

为什么要使用直接内存

直接内存,其实就是不受 JVM 控制的内存。相比于堆内存有几个优势:
1、减少了垃圾回收的工作,因为垃圾回收会暂停其他的工作。
2、加快了复制的速度。因为堆内在 flush 到远程时,会先复制到直接内存(非堆内存),然后再发送,而堆外内存相当于省略掉了这个工作。
3、可以在进程间共享,减少 JVM 间的对象复制,使得 JVM 的分割部署更容易实现。
4、可以扩展至更大的内存空间。比如超过 1TB 甚至比主存还大的空间。

直接内存的缺点

直接内存有很多好处,我们还是应该要了解它的缺点:
1、 堆外内存难以控制,如果内存泄漏,那么很难排查
2、 堆外内存相对来说,不适合存储很复杂的对象。一般简单的对象比较适合。

直接内存案例和场景分析

内存泄漏案例
工作中经常会使用 Java 的 Zip 函数进行压缩和解压,这种操作在一些对传输性能较高的的场景经常会用到。
程序将会申请 1kb 的随机字符串,然后不停解压。为了避免让操作系统陷入假死状态,我们每次都会判断操作系统内存使用率,在达到 60% 的时候,
我们将挂起程序(不在解压,只不断的让线程休眠)
通过访问 8888 端口,将会把内存阈值提高到 85%。

package ex15;

import com.sun.management.OperatingSystemMXBean;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpServer;

import java.io.*
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值