3

I have a java application which seems to allocate more and more memory from OS(but the heap size isn't growing at all!) It's an application communicating with a PLC so it needs quite some CPU.

for testing porpuse I have written this program, to be sure the problem isn't in some library:

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();
        }
    }

I have started the application like this

java -XX:NativeMemoryTracking=detail -Xmx1G -XX:+UseG1GC -XX:G1PeriodicGCInterval=10000 -XX:G1HeapWastePercent=10 -jar gctest.jar auto 100 3 10000000

this means the application allocates and releases 10MB every 100ms in 3 Threads.

Now I came across Native Memory Tracking which gives me this output for Internal

-                  Internal (reserved=367356KB, committed=367356KB)
                        (malloc=367324KB #3131147)
                        (mmap: reserved=32KB, committed=32KB)

At start it needed about 15MB now it neds almost 400MB

I just came across this documentation but it doesn't realy help me at all. Any clue how I could prevent java from allocating more and more memory from OS?

EDIT: The faster I allocate and release memory, the faster the memory in OS is growing

Community
  • 1
  • 1
user2071938
  • 2,055
  • 6
  • 28
  • 60
  • try moving List threaddata = new ArrayList<>(); inside the loop and see what happens. – Ray Tayek May 24 '19 at 05:23
  • this is just a test application, in my understanding things I instanciate and release is just affecting the heap. the odd thing is, the faster I release and allocate memory the faster the memory is growing – user2071938 May 24 '19 at 05:27
  • Moving the list doesn't change anything as the reference to the elememt in it is deleted immediately with clear(). But try reducing the amount of memory you give to the JVM by changing "-Xmx1G" to "-Xmx256M" and see what happens. It should start doing GC much earlier now. – Torben May 24 '19 at 05:39
  • 4
    You're not "releasing" objects - you're just making objects unreachable, which allows the garbage collector to release the memory at some later point. It's up to the garbage collector at which point. You've told Java it can grow up to 1Gb and that's what it's doing. – Erwin Bolwidt May 24 '19 at 05:41
  • @Torben Thank you! I already tried that, but -Xmx only affects the maximal heap size, but the heap size never get bigger than 100MB – user2071938 May 24 '19 at 05:43
  • @ErwinBolwidt You are right(that I'm not releasing the objects) but the 1Gb is just the max heap size, which gets never over 100Mb. the OS memory is increasing independently from the current Heap size – user2071938 May 24 '19 at 05:45
  • Heap memory would increase when the memory is freed from the stack memory. Try deleting the some variables, you will find the heap memory increasing. – Trishant Pahwa May 24 '19 at 06:02
  • How are you measuring all this? Normally in a Java VM, when you allocate things fast enough, it will expand your heap space (up to the maximum you specified). If you do this faster, then the heap grows faster. If you leave it running, does it eventually take all memory on your system, or are you just guessing that it will? – john16384 May 24 '19 at 11:28
  • @john16384 Hi! The problem is that the Heap isn't growing at all, but the JVM allocates more and more memory in the OS – user2071938 May 27 '19 at 06:31
  • 1
    You didn't answer any of my questions, and gave no new information. Java is being used on millions of systems daily, it doesn't have memory leaks like this unless there's something really fishy going on your system. So, my assumption is that you are misinterpreting what you are seeing. JVM can allocate more memory for example, but the used heap size you see might be small at the time you measure it (because it was just compacted). – john16384 May 28 '19 at 07:28
  • @john16384 I use VisualVM for monitoring the heap, the "Heap Size" ist constant over time, just "used heap" is going up and down. But In average "used heap" isn't growing at all, but the memory in OS (htop) is growing. – user2071938 May 28 '19 at 08:29

1 Answers1

2

I ran your snippet.

This is how it looks in VisualVM (JDK 11, standard settings):

enter image description here

I checked resource usage in Task Manager (Windows). It's constant.

So, I checked on Linux. Had to install htop, and upgrade the JDK, but I see no difference there. Here's the htop output after running the program for 5 minutes orso. VIRT and RES values stay the same, total memory consumption remained similar.

enter image description here

And here after 5 more minutes. Res changed to 119M, but I don't think it's anything to worry about.

enter image description here

From native memory tracking, taken 5 minutes apart:

[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)
john16384
  • 7,800
  • 2
  • 30
  • 44
  • thx for that! It is growing very slowly but constantly, so after a week or so my machine gets out of memory. – user2071938 May 28 '19 at 09:26
  • At what speed is it growing? I have it running still, it is at 120M res now, after 40 minutes, so maybe 1 MB every 20 minutes? Edit: It just jumped to 129M, then backed down to 128M. – john16384 May 28 '19 at 09:32
  • You say after a week it runs out of memory... is that with the snippet you posted? – john16384 May 28 '19 at 09:38
  • "yes" because I limited the memory with 500M in systemd, but with my real application the system gets ouf of memory(without limitation) – user2071938 May 28 '19 at 09:51
  • So, since you limited it with -Xmx1G (1 GB), and you limit it in systemd with 0.5 GB, then the JVM would crash when it tries to allocate more than 0.5 GB? This can happen when the VM decides it needs more space to work with (even though most of it is garbage.. it depends on the speed that memory gets used/discarded). How about you limit the VM to the actual amount you want it limited at, like -Xmx400M or something? – john16384 May 28 '19 at 09:56
  • Also, see my last snapshot, RES went down (and SHR as well)... I still don't see any kind of increasing memory consumption. Of course, the heap may grow at any time if the VM feels like it needs more, for any reason (but never more than what you set with -Xmx). A reason that it needs more can also be to keep allocations fast, and run GC less often. – john16384 May 28 '19 at 09:59
  • I looked into this a bit further. The `Internal` value contains allocations from `ByteBuffer.allocateDirect` but also from monitoring tools (like profilers, visualvm probably). Are you using any kind of instrumentation, agents etc? See this for example: https://stackoverflow.com/questions/44943675/java-process-memory-usage-keeps-increasing-and-java-native-memory-tracking-shows – john16384 May 28 '19 at 10:30
  • I just use visualVM for inspecting the heap because of the problem with the memory – user2071938 May 28 '19 at 10:48
  • which platform and jdk version do you use? – user2071938 May 28 '19 at 12:55
  • On the debian linux machine it was openjdk version "11.0.3" 2019-04-16, on Windows 10 it was Oracle JDK 11.0.1 – john16384 May 28 '19 at 13:13