-2

I'm currently trying to get servers direct memory value and store it into database, but I'm getting 0 value all the time, does my method fails to return the correct value of 500 MB.

The method I have is this:

import java.lang.management.BufferPoolMXBean;
import java.lang.management.ManagementFactory;
...
public int toGb(long valueInBytes) {
    return (int) (valueInBytes / (1024 * 1024 * 1024));
}

public int getMemoryDirect() {
    long memoryDirect = 0;
    List<BufferPoolMXBean> pools = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
    for(BufferPoolMXBean pool : pools) {
        if(pool.getName().equals("direct")) {
            memoryDirect = pool.getTotalCapacity();
        }
    }
    return toGb(memoryDirect);
}

Is there other way to retrieve this value?

Any help is apprecheated :)

lpkej
  • 417
  • 4
  • 13
  • 1
    Do any of the pool names actually equal "direct"? If they don't, of course you will return 0. – Michael Aug 06 '19 at 13:47
  • 2
    If the correct value is `500 MB` and you put it in GB, it will be `0.5 GB`. But `toGb()` method return an `int`, so `(int)0.5 = 0`. – Fifi Aug 06 '19 at 13:47
  • @Michael so it seems direct itself is ```0```. – lpkej Aug 06 '19 at 13:54
  • @Fifi Yeah if the value is less than ```1000``` it will always continue the int value of ```0```, now the problem is that direct is ```0```. – lpkej Aug 06 '19 at 13:55
  • @lpkej You can use a debugger to see if you enter the `for` loop and if you enter the `if` condition. It can help you – Fifi Aug 06 '19 at 13:57
  • @Fifi the pool name is ```null``` so it won't go inside if block and returns default ```0``` value. – lpkej Aug 06 '19 at 14:10
  • @lpkej Are you sure that you have set a name for the pools ? – Fifi Aug 06 '19 at 14:13
  • @Fifi the code you see is what all I did with pools actually. – lpkej Aug 06 '19 at 14:15

2 Answers2

1

Your problem here probably lies in the toGb method. In Java, integer division is truncating. This means that if you have 500 MB intended to be returned by the method (500*1024*1024) and intend to return it as an integer gigabyte value, you divide by (1024*1024*1024), which will always return 0. You can remedy this by attempting to return a floating point value (e.g. double or float) instead.

Alternatively, your memoryDirect variable may never have been set, if for no pool the name equals "direct". In this case, memoryDict will also always be 0.

Avi
  • 2,359
  • 1
  • 9
  • 21
  • Okay so I've tried to just print what value ```memoryDirect``` actually has (without ```toGB```) and it returns 0. So does this means this method will not get me the direct value.. – lpkej Aug 06 '19 at 13:53
  • 4
    Either the `pools` variable is empty, so you're not iterating in the loop in the first place, or the pools.getName() strings are not in the format you think they are. You can debug the output of pools.size() and the pools.getName() strings to check which is the case. – Avi Aug 06 '19 at 13:55
  • So in debugger the pool ```objName```is ```null``` it won't get inside the ```if``` statement and returns ```memoryDirect``` default value ```0```. I know that there is a ```meminfo``` file in ```proc``` directory in the server where the Direct values are specified:DirectMap4k, DirectMap2M, DirectMap1G. Any ideas how to reach these values? – lpkej Aug 06 '19 at 14:05
  • 1
    Unfortunately I don't have too much experience with mxbeans or ManagementFactory, so I can't help past this. However, I did find [this question](https://stackoverflow.com/questions/20058489/is-there-a-way-to-measure-direct-memory-usage-in-java), which may or may not help you. Good luck! – Avi Aug 06 '19 at 14:14
  • There's ```sun.misc.VM.maxDirectMemory()``` piece of code that returns the value I need, but it has warning ```Access restriction: The type 'VM' is not API``` and due to requirements unfortunately I can't use. Hope this link helps other tho! – lpkej Aug 06 '19 at 15:36
0

I had to write a custom parser for XX:MaxDirectMemorySize value, basically checking if the value specified in G/M/K/none(B) and do convertion accordingly.

And for testing locally create setenv.bat file where you can specify your custom arguments - f.e. set "CATALINA_OPTS=%CATALINA_OPTS% XX:MaxDirectMemorySize=100M" it will get that 100M do stuff with it.

And make sure to add this variable manualy in VM Arguments in Window > Show View > Servers > (chosen server) > Open launch configuration > (x)= Arguments

In the Console at the top you should be able to locate XX:MaxDirectMemorySize argument being set by Catalina:

enter image description here

lpkej
  • 417
  • 4
  • 13