sb15
sb15

Reputation: 67

showing incorrect answer for total physical memory size in java

this is the code

import java.lang.management.ManagementFactory;

public class MemorySize {

   public static void main(String[] args){
    com.sun.management.OperatingSystemMXBean mxbean = 
    (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    System.out.println(mxbean.getTotalPhysicalMemorySize() + " Bytes "); 

the above code gives me the output values as 2147483647 Bytes which is equal to 1.99 GB. But the actual installed memory(RAM) is 3.00 GB (2.30 GB usable) .how can I get the correct value i.e, 2.30 gb. please help.

Upvotes: 3

Views: 2075

Answers (3)

Stephen C
Stephen C

Reputation: 718946

In both Windows and Linux, the getTotalPhysicalMemorySize method is implemented by asking the operating system. In the case of Linux, an OpenJDK 11 JVM does that with the following C code:

jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES);
return (num_avail_physical_pages * page_size);

If you check the manual page for sysconf(3) it says this:

  • _SC_PHYS_PAGES: The number of pages of physical memory.

  • _SC_AVPHYS_PAGES: The number of currently available pages of physical memory.

Another source tells me this:

The value returned for _SC_AVPHYS_PAGES is the amount of memory the application can use without hindering any other process (given that no other process increases its memory usage).

So as you can see, this is not the total physical RAM. Rather it is the physical RAM that is "available".

You can read the above as (also) capping the value to the amount of RAM that a process could possibly use. With a 32 bit JVM, memory architecture considerations limit a single process to a lot less than 4GB of address space. For Windows, the limit is around 2GB.

(This is on Linux / OpenJDK 11. I haven't checked for other platforms and versions.)

Either way, the method returns what it returns. AFAIK, it is the best you can get using Pure Java.


"How can I get the correct value i.e, 2.30 g"

You may need to use System.exec(...) to run some platform-specific utility and scrape the information out of its output. Or implement a native method that asks the OS a different question.

However, you probably should not be using your-called "correct" value for sizing your JVM. If you try to use all of the physical RAM, you are liable to push the OS into dangerous thrashing behavior. (You may wake up the dreaded oomkiller ... which may then pick the wrong thing to kill!)

Upvotes: 1

Pratik
Pratik

Reputation: 67

Have you checked if there memory space for buffer/cache? if Yes. then (com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); does not give you the space used by buffer/cache. you may need to try reading

/proc/meminfo file for proper memory information.

Upvotes: 0

Zanson
Zanson

Reputation: 4031

The maximum memory a 32bit process is allowed to take is often only 2GB. If you use a 64bit JVM you should see the full size.

Upvotes: 0

Related Questions