public class Test {
public static void main(String[] args) {
long heapsize = Runtime.getRuntime().totalMemory();
System.out.println("heapsize is :: " + heapsize/(1024*1024));
}
}
The output is:
heapsize is :: 245
Does this mean my runtime has only 245M memory? My computer has 8GB memory. I doubt output this is correct, since the running of Eclipse alone will consume a lot more than 245M.
In Eclipse, I click Windows->Preferences->Java->Installed JREs, and set Default JVM arguments as follows:
-ea -Xms256m -Xmx4096M
Then run the test again. It still prints out the same number, 245. How could this happen?
Edited: from Java doc for Runtime.getRuntime().totalMemory():
Returns the total amount of memory in the Java virtual machine.
The value returned by this method may vary over time, depending on the
host environment.
Your program doesn't run in Eclipse's heap space. Eclipse spawns off a separate JVM for your program.
Runtime.totalMemory() does indeed return the current heap size.
The -Xms argument specifies the initial heap size. Java will expand if it cannot free up enough memory through garbage collection until it reaches the maximum, as set by -Xmx. At this point, the JVM will exit with an OutOfMemoryError.
Java memory management is a complex topic, involving garbage collection, moving objects from nursery to tenured space, etc.
Related
I am playing around with Java, parameter -Xms and class Runtime.
I see that JVM allocates about 15% of the memory that is available - regardless how much it is.
Runtime rt Runtime.getRuntime ();
long total = rt.totalMemory ()
long free = rt.freeMemory ();
That is the case if I start my programm with paramter
-Xms4000m
as well as with
-Xms90m
I see the difference of Xms in the result of totalMemory.
I understand the strategy of allocating more from the beginning to avoid expensive reallocation.
But I do not know if that is in place here AND how I can meter the real memory-consumption of my program.
If your're using the Oracle JVM, you can use the command line tool jmap or the GUI tool jvisualvm to measure the heap consumption of your Java program.
Get the PID of the application and you can use top command in the below way to print out the statistics.
top -b | grep PID
You can see how the memory is utilized over time.
Am I right in thinking that when one specifies VM arguments in an IDE (I'm using NetBeans in this instance), that these arguments are only passed when the code is run through the IDE itself?
Essentially, I'd like to specify that when my program runs, the VM's minimum/initial heap size is 2Gb. I can do this using the -Xms2048m command, but I'm wondering if there's some way to achieve this without having to type a command (for the customer's sake).
Even thought I set the VM argument in NetBeans, and Launch4J (I wrap the JAR into an EXE file), when the program boots & outputs the Runtime's total memory size, it always gives ~120Mb.
What am I missing?
Edit: I output the total memory size using...
int mb = 1024 * 1024;
System.out.println("Max Memory: " + Runtime.getRuntime().totalMemory() / mb);
Edit 2: Could one not create a initialising program that takes no arguments, but starts the main program with the relevant VM arguments? Something like...
public class Main {
public static void main(String[] args) {
String execName = new File(new File("").getAbsolutePath()) + "\\Program.exe";
Runtime rt = Runtime.getRuntime();
rt.exec("java -Xms2048m -Xmx4096m -jar " + execName);
}
}
The only way to do this is to have the program start another copy of the program witht eh heap you want. Note: the end user might not want 2 GB e.g.
If they have 32-bit windows they cannot e.g. if their default is only 120 MB, they most likely have a 32-bit windows client JVM which can't be 2 GB. If they have 32 GB or more they might want more than 2 GB.
BTW Gb = Giga-bit, Mb = Mega-bit, GB = Giga Byte. MB = Mega Byte.
No, You can't change the heap size programatically. Command line is the only way
Since the values must be set during JVM initialization,You cannot.
Some Useful discussion on the same on oracle forums.
And on SO :programatically setting max java heap size
Heap is able to shrink after GC iteration if GC decides that there are too many unused heap space allocated. Maybe that is way after your application starts it shows you the same size each time.
And also -Xms seems to set initial size of heap, not minimum
C:\Users\AStybaev>java -X
...
-Xms<size> set initial Java heap size
...
My JVM heap max is configured at 8GB on the name node for one of my hadoop clusters. When I monitor that JVM using JMX, the reported maximum is constantly fluctuating, as shown in the attached image.
http://highlycaffeinated.com/assets/images/heapmax.png
I only see this behavior on one (the most active) of my hadoop clusters. On the other clusters the reported maximum stays fixed at the configured value. Any ideas why the reported maximum would change?
Update:
The java version is "1.6.0_20"
The heap max value is set in hadoop-env.sh with the following line:
export HADOOP_NAMENODE_OPTS="-Xmx8G -Dcom.sun.management.jmxremote.port=8004 $JMX_SHARED_PROPS"
ps shows:
hadoop 27605 1 99 Jul30 ? 11-07:23:13 /usr/lib/jvm/jre/bin/java -Xmx1000m -Xmx8G
Update 2:
Added the -Xms8G switch to the startup command line last night:
export HADOOP_NAMENODE_OPTS="-Xms8G -Xmx8G -Dcom.sun.management.jmxremote.port=8004 $JMX_SHARED_PROPS"
As shown in the image below, the max value still varies, although the pattern seems to have changed.
http://highlycaffeinated.com/assets/images/heapmax2.png
Update 3:
Here's a new graph that also shows Non-Heap max, which stays constant:
http://highlycaffeinated.com/assets/images/heapmax3.png
According to the MemoryMXBean documentation, memory usage is reported in two categories, "Heap" and "Non-Heap" memory. The description of the Non-Heap category says:
The Java virtual machine manages memory other than the heap (referred as non-heap memory).
The Java virtual machine has a method area that is shared among all threads. The method area belongs to non-heap memory. It stores per-class structures such as a runtime constant pool, field and method data, and the code for methods and constructors. It is created at the Java virtual machine start-up.
The method area is logically part of the heap but a Java virtual machine implementation may choose not to either garbage collect or compact it. Similar to the heap, the method area may be of a fixed size or may be expanded and shrunk. The memory for the method area does not need to be contiguous.
This description sounds a lot like the permanent generation (PermGen), which is indeed part of the heap and counts against the memory allocated using the -Xmx flag. I'm not sure why they decided to report this separately since it is part of the heap.
I suspect that the fluctuations you're seeing are a result of the JVM shrinking and growing the permanent generation, which would cause the reported max heap space available for non-PermGen uses to change accordingly. If you could get a sum of the Heap and Non-Heap maxes as reported by JMX and this sum stays constant at the 8G limit, that would verify this hypothesis.
One possibility is that the JVM survivor space is fluctuating in max-size.
The JVM max-size reported by JMX via the HeapMemoryUsage.max attribute is not the actual max-size of the heap (i.e. the one set with -Xmx )
The reported value is the max heap size minus the max survivor space size
To get the total max heap size, add the two jmx attributes:
java.lang:type=Memory/HeapMemoryUsage.max + java.lang:type=MemoryPool,name=Survivor Space/Usage.max
(tested on oracle jdk 1.7.0_45)
What does mean "Maximum Heap Size = Unlimited" in a j2me device?
For example of device:
http://www.developer.nokia.com/Devices/Device_specifications/E71/
Can I increase the app's heap size ?
Heap Memory means in programming, an area of memory reserved for data that is created at runtime that is, when the program actually executes. In contrast, the stack is an area of memory used for data whose size can be determined when the program is compiled.
Java heap is the heap size allocated to JVM applications which takes care of the new objects being created. If the objects being created exceed the heap size, it will throw an error saying memoryOutof Bound
Java's default heap size limit is 128MB. If you need more than this, you should use the -Xms and -Xmx command line arguments when launching your program:
java -Xms -Xmx
We can also give like in this format also.format is : -mx256m..Sometimes it will show error if you are using
java -Xms -Xmx format..In that case use -mx256m this.value can be changed..
I see some strange behavior on the maximum heap size I get on Sun's JVM, compared to JRockit.
I'm running IDEA on 64-bit VMs on a 64-bit system (Ubuntu 11.04). The JVM versions I'm testing are: Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode) (which I got with apt-get install sun-java6-jdk, and Oracle JRockit(R) (build R28.1.3-11-141760-1.6.0_24-20110301-1432-linux-x86_64, compiled mode) (which I downloaded from Oracle's site a couple of months ago).
If I pass the parameters -Xms1g -Xmx3g, IDEA will report a maximum heap size of 1820M on Sun's JVM, and 3072M (as expected) on JRockit.
If I pass -Xms2g -Xmx4g, IDEA will report 3640M on Sun's and 4096M on JRockit.
What is happening? What are those mystic numbers 1820M and 3640M = 2*1820M? Isn't it possible to run Sun's JVM with the exact heap size I want?
EDIT:
An answer has been deleted, so just to bring my comments back: please note that I'm talking about the MAX size, not the current size. Consider that I've researched a lot before asking the question here, so there's no need to teach the meaning of Xms, Xmx or any of the other of the parameters that specify the size of regions of the memory (those can be found elsewhere).
EDIT2:
I wrote the following simple code to test this behavior:
public static void main(String[] args) throws Exception {
while (true) {
final Runtime r = Runtime.getRuntime();
System.out.println("r.freeMemory() = " + r.freeMemory()/1024.0/1024);
System.out.println("r.totalMemory() = " + r.totalMemory()/1024.0/1024);
System.out.println("r.maxMemory() = " + r.maxMemory()/1024.0/1024);
Thread.sleep(1000);
}
}
Then I ran it with -Xmx100m, -Xmx110m, -Xmx120m, etc... for many many different values, both on Sun's JVM and o JRockit. Sun's will always report a bizarre value for maxMemory() and would grow on big steps (like 30M) between runs. JRockit reported the exact value every time.
The Xms and Xmx only serve to indicate the minimum and maximum sizes of the allocated heap. The actual size of the allocated heap could/will be a value between the minimum and maximum, as the JVM can resize the heap, especially during object allocation events or garbage collection events.
If you need the JVM to use the "exact" heap size, you can specify Xms and Xmx values that are close enough to each other, so that heap resizing does not occur. Of course, these values must correspond to a contiguous amount of free memory.
The above section assumed something else, and can be ignored for practical purposes.
Based on the code used to calculate heap size, it should be noted that Runtime.maxMemory() returns a value that does not correspond to the value passed in the Xmx flag for the Hotspot JVM; the documentation is vague in stating that it will simply return a value that indicates the memory available for the JVM to use.
Inferring from your posted code's behavior, heap resizing will result in different values being reported for different invocations of Runtime.maxMemory(). Also, it would be needless to point out that the JRockit JVM reports the value passed in via Xmx flag.