具有恒定堆大小的Java进程在操作系统中分配越来越多的内存

具有恒定堆大小的Java进程在操作系统中分配越来越多的内存,java,java-memory-leaks,Java,Java Memory Leaks,我有一个java应用程序,它似乎从操作系统分配越来越多的内存(但堆大小根本没有增长!)它是一个与PLC通信的应用程序,因此需要相当多的CPU 为了测试porpuse,我编写了这个程序,以确保问题不在某些库中: public static void main(String[] args) { Random rand= new Random(); if (args[0].equals("auto")) { for(int i = 0; i<

我有一个java应用程序,它似乎从操作系统分配越来越多的内存(但堆大小根本没有增长!)它是一个与PLC通信的应用程序,因此需要相当多的CPU

为了测试porpuse,我编写了这个程序,以确保问题不在某些库中:

public static void main(String[] args) {
    Random rand= new Random();
    if (args[0].equals("auto")) {
        for(int i = 0; i< Integer.valueOf(args[2]);i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    List<byte[]> threaddata = new ArrayList<>();
                    while(true) {                               
                        byte[] arr = new byte[Integer.valueOf(args[3])];
                        rand.nextBytes(arr);
                        threaddata.add(arr);
                        Thread.sleep(Long.valueOf(args[1]));
                        threaddata.clear();
                        Thread.sleep(Long.valueOf(args[1]));                                
                    }
                }                   
            }).start();
        }
    }
这意味着应用程序在3个线程中每100ms分配和释放10MB

现在我遇到了
本机内存跟踪
,它为
内部

-                  Internal (reserved=367356KB, committed=367356KB)
                        (malloc=367324KB #3131147)
                        (mmap: reserved=32KB, committed=32KB)
一开始它需要15MB左右,现在几乎需要400MB

我只是偶然发现,但这对我一点帮助都没有。有什么线索可以阻止java从OS分配越来越多的内存吗

编辑:我分配和释放内存的速度越快,操作系统中的内存增长越快

我运行了你的代码片段

这是它在VisualVM(JDK 11,标准设置)中的外观:

我在任务管理器(Windows)中检查了资源使用情况。它是恒定的

所以,我选择了Linux。必须安装
htop
,并升级JDK,但我看不出有什么不同。以下是运行程序5分钟后的
htop
输出。VIRT和RES值保持不变,总内存消耗量保持不变

再过5分钟就到了。Res改为119M,但我不认为这有什么好担心的

从本机内存跟踪,相隔5分钟:

[root@Ukyo 130 /download]# while sleep 300; do jcmd 16920 VM.native_memory |grep Internal -A 3; done
               Internal (reserved=605KB, committed=605KB)
                        (malloc=565KB #1151)
                        (mmap: reserved=40KB, committed=40KB)

               Internal (reserved=605KB, committed=605KB)
                        (malloc=565KB #1151)
                        (mmap: reserved=40KB, committed=40KB)

尝试移动列表threaddata=new ArrayList();这只是一个测试应用程序,据我所知,实例化和发布的东西只会影响堆。奇怪的是,我释放和分配内存的速度越快,内存增长的速度就越快移动列表不会改变任何东西,因为对其中元素的引用会立即用clear()删除。但是尝试通过将“-Xmx1G”更改为“-Xmx256M”来减少给JVM的内存量,看看会发生什么。它现在应该更早地开始执行GC,你不是在“释放”对象,你只是使对象不可访问,这允许垃圾收集器在稍后释放内存。这取决于垃圾收集器在哪一点上。您告诉Java它可以增长到1Gb,这就是它正在做的。您没有回答我的任何问题,也没有提供任何新信息。Java每天都在数百万个系统上使用,它不会有像这样的内存泄漏,除非你的系统真的出了问题。所以,我的假设是你误解了你所看到的。例如,JVM可以分配更多内存,但在测量时,您看到的使用的堆大小可能很小(因为它刚刚被压缩)。谢谢!它的增长非常缓慢但持续不断,所以大约一周后,我的机器就会失去记忆。它的增长速度是多少?我让它仍在运行,它现在的分辨率是120米,40分钟后,所以可能每20分钟1 MB?编辑:它刚跳到129M,然后又回落到128M。你说一周后它的内存就用完了。。。这就是您发布的代码片段吗?“是的”,因为我在systemd中限制了500米的内存,但在我的实际应用程序中,系统获得了ouf内存(没有限制),因此,由于您使用-Xmx1G(1 GB)限制它,而在systemd中限制它为0.5 GB,那么当JVM试图分配超过0.5 GB的内存时,它会崩溃吗?当VM决定它需要更多的空间来处理时,就会发生这种情况(即使大部分空间都是垃圾..这取决于内存被使用/丢弃的速度)。如何将虚拟机限制在您希望限制在的实际数量,比如-Xmx400M或其他什么?
[root@Ukyo 130 /download]# while sleep 300; do jcmd 16920 VM.native_memory |grep Internal -A 3; done
               Internal (reserved=605KB, committed=605KB)
                        (malloc=565KB #1151)
                        (mmap: reserved=40KB, committed=40KB)

               Internal (reserved=605KB, committed=605KB)
                        (malloc=565KB #1151)
                        (mmap: reserved=40KB, committed=40KB)