The JVM -Xmx argument lets one set the max heap size for the JVM to some value. But, is there a way to make that value dynamic? In other words, I want to tell the JVM "look, if you need it, just keep taking RAM from the system until the system is out."
Two-part reason for asking:
First, the app in question can use a really wide range of ram depending on what the user is doing, so the conceptual min and max values are pretty far apart. Second, it would seem that the JVM reserves the max heap space from virtual memory at boot time. This particular app is run on a pretty wide variety of hardware, so picking a "one-size-fits-all" max heap space is hard since it has to be low enough to run on low-end hardware, but we'd really like to be able to take advantage of really beefy machines if they're available.
But, is there a way to make that value dynamic?
Literally, no. The max heap size is set at JVM launch time and cannot be increased.
In practice, you could just set the max heap size to as large as your platform will allow, and let the JVM grow the heap as it needs. There is an obvious risk in doing this; i.e. that your application will use all of the memory and cause the user's machine to grind to a halt. But that risk is implicit in your question.
EDIT
It is worth noting that there are various -XX... GC tuning options that allow you to tweak the way that the JVM expands the heap (up to the maximum).
Another possibility is to split your application into 2 parts. The first part of the application does all of the preparation necessary to determine the "size" of the problem. Then it works out an appropriate max heap size, and launches the memory hungry second part of the application in a new JVM.
This only works if the application can sensibly be partitioned as above.
This only works if it is possible to compute the problem size. In some cases, computing the problem size is tantamount to computing the result.
It is not clear that you will get better overall performance than if you just let the heap grow up to a maximum size.
It doesn't. It could, and it probably should:
-Xmx90% // 90% of physical memory
However, a default implicit, 100%, is proabbly not a good idea.
A program written in a non-GC language manages its memory very diligently, it will prune any garbage as soon as possible. It makes sense to allow it to get any memory it requests, assuming it's responsible for prompt garbage disposal.
A GC language is different. It collects garbage only when necessary. As long as there's room, it doesn't care about garbage lingering around. If it could get all the memory it would like to have, it would get all the memory in the computer.
So a GC programmer doesn't have to worry about disposing every piece of garbage any more, but he still have to have a general idea of the tolerable garbage/live object ratio, and instruct GC with -Xmx.
Basically, you can't adapt to various users' hardware using pure Java: that's when a little bit of shell/batch scripting can come in handy.
I do just that on OS X and Linux: I've got a little bash shell script that takes care of finding the correct JVM parameters depending on the hardware the application is run on and then calling the JVM.
Note that if you're providing a desktop Java application, then you may want to use something like izpack to provide your users an installer:
http://izpack.org
I don't know at all if Java Web Start can be used to provide different JVM parameters depending on the user's config (probably not, and JWS really s*cks big time anyway if you plan to provide a professional looking desktop app).
There is a JDK Enhancement Proposal (JEP) 8204088
https://bugs.openjdk.java.net/browse/JDK-8204088
http://openjdk.java.net/jeps/8204088
"Dynamic Max Memory Limit"
that suggests to introduce CurrentMaxHeapSize:
To dynamically limit how large the committed memory (i.e. the heap
size) can grow, a new dynamically user-defined variable is introduced:
CurrentMaxHeapSize. This variable (defined in bytes) limits how large
the heap can be expanded. It can be set at launch time and changed at
runtime. Regardless of when it is defined, it must always have a value
equal or below to MaxHeapSize (Xmx - the launch time option that
limits how large the heap can grow). Unlike MaxHeapSize,
CurrentMaxHeapSize, can be dynamically changed at runtime.
The expected usage is to setup the JVM with a very conservative Xmx
value (which is shown to have a very small impact on memory footprint)
and then control how large the heap is using the CurrentMaxHeapSize
dynamic limit.
While there are no signs of this feature actively being worked at,
it's relatively new JEP (from 2018), so I would still keep this in mind.
And company Jelastic (jelastic.com) has made a working prototype
of JEP 8204088 for G1 garbage collector:
See description at http://mail.openjdk.java.net/pipermail/hotspot-gc-dev/2018-May/022077.html
and list of patches for OpenJDK
http://cr.openjdk.java.net/~tschatzl/jelastic/cmx/
Related
In the spirit of question Java: Why does MaxPermSize exist?, I'd like to ask why the Oracle JVM uses a fixed upper limit for the size of its memory allocation pool.
The default is 1/4 of your physical RAM (with upper & lower limit); as a consequence, if you have a memory-hungry application you have to manually change the limit (parameter -Xmx), or your app will perform poorly, possible even crash with an OutOfMemoryError.
Why does this fixed limit even exist? Why does the JVM not allocate memory as needed, like native programs do on most operating systems?
This would solve a whole class of common problems with Java software (just Google to see how many hints there are on the net on solving problems by setting -Xmx).
Edit:
Some answers point out that this will protect the rest of the system from a Java program with a run-away memory leak; without the limit this would bring the whole system down by exhausting all memory. This is true. However, it is equally true for any other program, and modern OSes already let you limit the maximum memory for a programm (Linux ulimit, Windows "Job Objects"). So this does not really answer the question, which is "Why does the JVM do it differently from most other programs / runtime environments?".
Why does this fixed limit even exist? Why does the JVM not allocate memory as needed, like native programs do on most operating systems?
The reason is NOT that the GC needs to know before hand what the maximum heap size can be. The JVM is clearly capable of expanding its heap ... up to the maximum ... and I'm sure it would be a relatively small change to remove that maximum. (After all, other Java implementations do this.) And it would equally be possible to have a simple way to say "use as much memory as you like" to the JVM.
I'm sure that the real reason is to protect the host operating system against the effects of faulty Java applications using all available memory. Running with an unbounded heap is potentially dangerous.
Basically, many operating systems (e.g. Windows, Linux) suffer serious performance degradation if some application tries to use all available memory. On Linux for example, the system may thrash badly, resulting in everything on the system running incredibly slowly. In the worst case, the system won't be able to start new processes, and existing processes may start crashing when the operating system refuses their (legitimate) requests for more memory. Often, the only option is to reboot.
If the JVM ran with an unbounded heap by default, any time someone ran a Java program with a storage leak ... or that simply tried to use too much memory ... they would risk bringing down the entire operating system.
In summary, having a default heap bound is a good thing because:
it protects the health of your system,
it encourages developers / users to think about memory usage by "hungry" applications, and
it potentially allows GC optimizations. (As suggested by other answers: it is plausible, but I cannot confirm this.)
EDIT
In response to the comments:
It doesn't really matter why Sun's JVMs live within a bounded heap, where other applications don't. They do, and advantages of doing so are (IMO) clear. Perhaps a more interesting question is why other managed languages don't put a bound on their heaps by default.
The -Xmx and ulimit approaches are qualitatively different. In the former case, the JVM has full knowledge of the limits it is running under and gets a chance to manage its memory usage accordingly. In the latter case, the first thing a typical C application knows about it is when a malloc call fails. The typical response is to exit with an error code (if the program checks the malloc result), or die with a segmentation fault. OK, a C application could in theory keep track of how much memory it has used, and try to respond to an impending memory crisis. But it would be hard work.
The other thing that is different about Java and C/C++ applications is that the former tend to be both more complicated and longer running. In practice, this means that Java applications are more likely to suffer from slow leaks. In the C/C++ case, the fact that memory management is harder means that developers don't attempt to build single applications of that complexity. Rather, they are more likely to build (say) a complex service by having a listener process fork of child processes to do stuff ... and then exit. This naturally mitigates the effect of memory leaks in the child process.
The idea of a JVM responding "adaptively" to requests from the OS to give memory back is interesting. But there is a BIG problem. In order to give a segment of memory back, the JVM first has to clear out any reachable objects in the segment. Typically that means running the garbage collector. But running the garbage collector is the last thing you want to do if the system is in a memory crisis ... because it is pretty much guaranteed to generate a burst of virtual memory paging.
Hm, I'll try summarizing the answers so far.
There is no technical reason why the JVM needs to have a hard limit for its heap size. It could have been implemented without one, and in fact many other dynamic languages do not have this.
Therefore, giving the JVM a heap size limit was simply a design decision by the implementors. Second-guessing why this was done is a bit difficult, and there may not be a single reason. The most likely reason is that it helps protect a system from a Java program with a memory leak, which might otherwise exhaust all RAM and cause other apps to crash or the system to thrash.
Sun could have omitted the feature and simply told people to use the OS-native resource limiting mechanisms, but they probably wanted to always have a limit, so they implemented it themselves.
At any rate, the JVM needs to be aware of any such limit (to adapt its GC strategy), so using an OS-native mechanism would not have saved much programming effort.
Also, there is one reason why such a built-in limit is more important for the JVM than for a "normal" program without GC (such as a C/C++ program):
Unlike a program with manual memory management, a program using GC does not really have a well-defined memory requirement, even with fixed input data. It only has a minimum requirement, i.e. the sum of the sizes of all objects that are actually live (reachable) at a given point in time. However, in practice a program will need additional memory to hold dead, but not yet GCed objects, because the GC cannot collect every object right away, as that would cause too much GC overhead. So GC only kicks in from time to time, and therefore some "breathing room" is required on the heap, where dead objects can await the GC.
This means that the memory required for a program using GC is really a compromise between saving memory and having good througput (by letting the GC run less often). So in some cases it may make sense to set the heap limit lower than what the JVM would use if it could, so save RAM at the expense of performance. To do this, there needs to be a way to set a heap limit.
I think part of it has to do with the implementation of the Garbage Collector (GC). The GC is typically lazy, meaning it will only start really trying to reclaim memory internally when the heap is at its maximum size. If you didn't set an upper limit, the runtime would happily continue to inflate until it used every available bit of memory on your system.
That's because from the application's perspective, it's more performant to take more resources than exert effort to use the resources you already have to full utilization. This tends to make sense for a lot of (if not most) uses of Java, which is a server setting where the application is literally the only thing that matters on the server. It tends to be slightly less ideal when you're trying to implement a client in Java, which will run amongst dozens of other applications at the same time.
Remember that with native programs, the programmer typically requests but also explicitly cleans up resources. That isn't typically true with environments who do automatic memory management.
It is due to the design of the JVM. Other JVM's (like the one from Microsoft and some IBM ones) can use all the memory available in the system if needed, without an arbitrary limit.
I believe it allows for GC-optimizations.
I think that the upper limit for memory is is linked to the fact that JVM is a VM.
As any physical machine has a given (fixed) ammount of RAM so the VM has one.
The maximal size makes the JVM easier to manage by the operating system and ensures some performance gains(less swapping).
Sun' JVM also works in quite limited hardware architecture(embedded ARM systems) and there the management of resources is crucial.
One answer that no-one above gave is that the JVM uses both heap and non-heap memory pools. Putting an upper limit on the heap defines not only how much memory is available for the heap memory pools, but it also defines how much memory is available for NON-HEAP usages. I suppose that the JVM could just allocate non-heap at the top of virtual memory and heap at the bottom of virtual memory and grow both toward each other.
Non-heap memory includes the DLLs or SOs that comprise the JVM and any native code being used as well as compiled Java code, thread stacks, native objects, PermGen (meta-data about compiled classes), among other uses. I've seen Java programs crash because so much memory was given to the heap that the application ran out of non-heap memory. This is where I learned that it can be important to reserve memory for non-heap usages by not setting the heap to be too large.
This makes a much bigger difference in a 32-bit world where an application often has only 2GB of virtual address space than it does in a 64-bit world, of course.
Would it not make more sense to separate the upper bound that triggers GC and the maximum that can be allocated ? Once the memory allocated hits the upper-bound, GC can kick in and release some memory to the free pool.
sort of like how I clean my desk that I share with my co-worker. I have a large desk, and my threshold of how much junk I can tolerate on the table is much less than the size of my desk. I don't need to have fill up every available inch before I garbage collect.
I could also return some of the desk space that I using to my co-worker, who is sharing my desk....I understand jvms don't return memory back to the system after they've allocated it to themselves, but it does not have to be that way no ?
It does allocate memory as needed, up to -Xmx ;)
One reason I can think of is that once the JVM allocates an amount of memory for its heap, it will never let it go. So if your heap has no upper bound, the JVM may just grab all the free memory on the system and then never let it go.
The upper bound also tells the JVM when it needs to do a full garbage collection. If your app is still under the upper bound, the JVM will postpone garbage collection and let the memory footprint of your application grow.
Native programs can die due to out of memory errors as well since native applications also have a memory limit: the memory available on the system - the memory already held by other applications.
The JVM also needs a contiguous block of system memory in order for garbage collection to be performed efficiently.
EDIT
Contiguous memory claim or here
The JVM will apparently let some memory go, but it is rare with the default configuration.
Why does Java not expand the heap size until it hits the OS-imposed process memory limit, in the same way .NET CLR does?
Is it just a policy made by JVM developers, or is an advantage of .NET CLR's architecture over JVM's one? In other words, if Oracle engineers want to implement automatic heap expansion for the JVM, are they able to do that?
Thanks
EDIT: I really think it is a bad design choice for java. It is not safe to set the Xmx as high as possible (e.g. 100 GB!). If a user need to run my code on bigger data, he may run it on a system with more available RAM. Why should I, as the developer, set the maximum available memory of my program? I do not know which size the data is !!!
The JVM increases the heap size when it needs to up to the maximum heap size you set. It doesn't take all the memory as it has to preallocate this on startup and you might want to use some memory for something else, like thread stacks, share libraries, off heap memory etc.
Why Java does not expand the heap size until it hits the OS-imposed process memory limit, in the same way .NET CLR does?
If you set the maximum heap size large enough, or use off heap memory, it will. It just won't do this by default. One reason is that heap memory has to be in main memory and cannot be swapped out without killing the performance of your machine (if not killing your machine) This is not true of C programs and expanding so much is worse than failing to expand.
If you have a JVM with a heap size of 10% more than main memory and you use that much, as soon as you perform a GC, which has to touch every page more than once, you are likely to find you need to power cycle the box.
Linux has a process killer when resources run out, and this doesn't trigger you might be luck enough to restart.
Is it just a policy made by JVM developers, or is an advantage of .NET CLR's architecture over JVM's one
A key feature of the JVM is that it is platform independent, so it has its own control. The JVM running at the limit of your process space is likely to prevent your machine from working (from heavy swapping) I don't know .NET avoids this from happening.
In other words, if Oracle engineers want to implement automatic heap expansion for the JVM, are they able to do that?
It does already as I have said, it's just not a good idea to allow it to use too much memory.
It is a developers decision to decide how much heap memory must be allowed for the java process. it is based on various factors like the project design, platform on which it is going to run etc.
We can set heap size properties
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
As you can see we set the initial heap size and if later JVM finds that more is needed then it can increase the heap size upto the maximum specified limit. Infact the size changes when we do GC(not a mandate). I had posted question on similar grounds. You can refer to it. So increase/decrease of heap size is done by JVM. All we have to do as developers is specify limit based on our requirements.
I have heard several people claiming that you can not scale the JVM heap size up. I've heard claims of the practical limit being 4 gigabytes (I heard an IBM consultant say that), 10 gigabytes, 32 gigabytes, and so on... I simply can not believe any of those numbers and have been wondering about the issue now for a while.
So, I have three part question I would hope someone with experience could answer:
Given the following case how would you tune the heap and GC settings?
Would there be noticeable hickups (pauses of JVM etc) that would be noticed by the end users?
Should this really still work? I think it should.
The case:
64 bit platform
64 cores
64 gigabytes of memory
The application server is client facing (ie. Jboss/tomcat web application server) - complete pauses of JVM would probably be noticed by end users
Sun JVM, probably 1.5
To prove I am not asking you guys to do my homework this is what I came up with:
-XX:+UseConcMarkSweepGC -XX:+AggressiveOpts -XX:+UnlockDiagnosticVMOptions -XX:-EliminateZeroing -Xmn768m -Xmx55000m
CMS should reduce the amount of pauses, although it comes with overhead. The other settings for CMS seem to default automatically to the number of CPUs so they seem sane to me. The rest that I added are extras that might do good or bad generally for performance, and they should probably be tested.
Definitely.
I think it's going to be difficult for anybody to give you anything more than general advice, without having further knowledge of your application.
What I would suggest is that you use VisualGC (or the VisualGC plugin for VisualVM) to actually look at what the garbage collection is doing when your app is running. Once you have a greater understanding of how the GC is working alongside your application, it'll be far easier to tune it.
#1. Given the following case how would you tune the heap and GC settings?
First, having 64 gigabytes of memory doesn't imply that you have to use them all for one JVM. Actually, it rather means you can run many of them. Then, it is impossible to answer your question without any access to your machine and application to measure and analyse things (knowing what your application is doing isn't enough). And no, I'm not asking to get access to your environment :)
#2. Would there be noticeable hickups (pauses of JVM etc) that would be noticed by the end users?
The goal of tuning is to find a good compromise between frequency and duration of (major) GCs. With a ~55g heap, GC won't be frequent but will take noticeable time, for sure (the bigger the heap, the longer the major GC). Using a Parallel or Concurrent garbage collector will help on multiprocessor systems but won't entirely solve this issue. Why do you need ~55g (this is mega ultra huge for a webapp IMO), that's my question. I'd rather run many clustered JVMs to handle load if required (at some point, the database will become the bottleneck anyway with a data oriented application).
#3. Should this really still work? I think it should.
Hmm... not sure I get the question. What is "this"? Instantiating a JVM with a big heap? Yes, it should. Is it equivalent to running several JVMs? No, certainly not.
PS: 4G is the maximum theoretical heap limit for the 32-bit JVM running on a 64-bit operating system (see Why can't I get a larger heap with the 32-bit JVM?)
PPS: On 64-bit VMs, you have 64 bits of addressability to work with resulting in a maximum Java heap size limited only by the amount of physical memory and swap space your system provides. (see How large a heap can I create using a 64-bit VM?)
Obviously heap size is not unlimited and the larger is the heap size, the more your JVM will eventually spend on GC. Though I think it is possible to set heap size quite high on 64-bit JVM, I still think it's not really practical. The advice here is better to have several JVMs running with the same parameters i.e. cluster of JBoss/Tomcat nodes running on the same physical machine and you will get better throughput.
EDIT: Also your GC behavior depends on the taxonomy of your heap. If you have a lot of short-living objects and each request to the server creates a lot of those, then your GC will collect a lot of garbage very often and thus on large heap size this will result in longer pauses. If you have very many long-living objects (e.g. caching most of your data in memory) and the amount of short-living objects is not that big, then having bigger heap size is OK.
As Chris Rice already wrote, I wouldn't expect any obvious problems with the GC for heap sizes up to 32-64GB, although there may of course be some point of your application logic, which can cause problems.
Not directly related to GC, but I would still recommend you to perform a realistic load test on your production system. I used to work on a project, where we had a similar setup (relatively large, clustered JBoss/Tomcat setup to serve a public web application) and without exaggeration, JBoss is not behaving very well under high load or with a high number of concurrent calls if you are using EJBs. JBoss is spending a lot of time in synchronized blocks when accessing and managing the EJB instance pools and if you opt for a cluster, it will even wait for intra-cluster network communication within these synchronized blocks. Be especially aware of poorly performing state replication, if you are using SFSBs.
Only to add some more switches I would use by default: -Xms55g can help to reduce the rampup time because it frees Java from the need to check if it can fall back to the initial size and allows also better internal initial sizing of memory areas.
Additionally we made good experiences with NewSize to give you a large young size to get rid of short term garbage: -XX:NewSize=1g Additionally most webapps create a lot of short time garbage that will never survive the request processing. You can even make that bigger. With Xms55g, the VM reserves a large chunk already. Maybe downsizing can help.
-Xincgc helps to clean the young generation incrementally and return the cpu often to the user threads.
-XX:CMSInitiatingOccupancyFraction=70 If you really fill all that memory, try to start CMS garbage collection earlier.
-XX:+CMSIncrementalMode puts the CMS into incremental mode to return the cpu to the user threads more often.
Attach to the process with jstat -gc -h 10 <pid> 1s and watch the GC working.
Will you really fill up the memory? I assume that 64cpus for request processing might even be able to work with less memory. What do you store in there?
Depending on your GC pause analysis, you may wish to implement Incremental mode whereby the long pause may be broken out over a period of time.
I have found memory architecture plays a part in large memory sizes. Applications in general don't perform as well if they use more than one memory bank. The JVM appears to suffer as well, esp the GC which has to sweep the whole memory.
If you have an application which doesn't fit into one memory bank, your application has to pull in memory which is not local to a processor and use memory local to another processor.
On linux you can run numactl --hardware to see the layout of processors and memory banks.
I know how to set the Java heap size in Tomcat and Eclipse. My question is why? Was there an arbitrary limit set on the initial heap back when Java was first introduced so the VM wouldn't grow over a certain size? It seems with most machines today with large memory space available this isn't something we should have to deal with.
Thanks,
Tom
Even now, the heap doesn't grow without limit.
When the oldest generation is full, should you expand it or just GC? Or should you only expand it if a GC doesn't free any memory?
.NET takes the approach you'd like: you can't tell it to only use a certain amount of heap. Sometimes it feels like that's a better idea, but other times it's nice to be able to have two processes on the same machine and know that neither of them will be able to hog the whole of the memory...
I glanced by this the other day, but I'm not sure if this is what you want: -XX:+AggressiveHeap. According to Sun:
This option instructs the JVM to push
memory use to the limit: the overall
heap is more than 3850MB, the
allocation area of each thread is
256K, the memory management policy
defers collection as long as possible,
and (beginning with J2SE 1.3.1_02)
some GC activity is done in parallel.
Because this option sets heap size, do
not use the -Xms or -Xmx options in
conjunction with -XX:+AggressiveHeap.
Doing so will cause the options to
override each other's settings for
heap size.
I wasn't sure if this really meant what I thought it meant, though - that you could just let the JVM gobble up heap space until it is satisfied. However, it doesn't sound like it's a good option to use for most situations.
I would think that it's good to be able to provide a limit so that if you have a memory issue it doesn't gobble up all the system memory leaving you with only a reboot option.
Java is a cross-platform system. Some systems (like Unix and derviates) have a ulimit command which allows you to limit how much memory a process can use. Others don't. Plus Java is sometimes run embedded, for example in a web browser. You don't want a broken applet to bring down your desktop (well, that was at least the idea but applets never really caught on but that's another story). Essentially, this option is one of the key cornerstones for sandboxing.
So the VM developers needed a portable solution: They added an option to the VM which would allow anyone (user, admin, web browser) to control how much RAM a VM could allocate tops. The needs of the various uses of Java are just too diverse to have one size fits all.
This becomes even more important today when you look at mobile devices. You desktop has 2-8GB RAM but your mobile has probably much less. And for these things, you really don't want one bad app to bring down the device because there might not even be a user who could check.
Is there a way to set heap size from a running Java program?
No.
What you can do with an app that has very variable heap requirements is to set your max heap size very high with -Xmx and tune -XX:MaxHeapFreeRatio and -XX:MinHeapFreeRatio so that the app will not hang on to a lot of memory when the heap shrinks (it does that with default settings).
But note that this may cause performance problems when the memory actually used by the app varies both strongly and quickly - in that case you're better off having it hang on to all the memory rather than give it back to the OS only to claim it again a second later. You might also want to fiddle with the GC options to ensure that the GC doesn't leave too much unclaimed objects lying around, which it tends to do when there's a lot of room for the heap to grow, and which would defeat the goal of wanting the heap size to adjust to the app's needs.
According to http://www.dreamincode.net/forums/showtopic96263.htm, you can't do this at runtime, but you can spawn another process with a different heap size.
You can tweak those settings when you start your application but once the JVM is up and running those values cannot be changed. Something like this:
java -Xms32m -Xmx512m FooBar
will set the minimum heap size to 32MB and the maximum heap size to 512MB. Once these are set, you cannot change them within the running program.
The consensus may indeed be that this is not possible, but we should be looking at the JVM source to see how it can be ergonomically controlled. It would be very nice to be able to have a JVMTI agent be able to adjust the heap/perm/tenured/new/&c sizing online/at runtime.
What would this do? it would allow agents to infer sizing adjustments based upon performance or footprint goals which will be important when moving JVMs into the Cloud.
You can use the -mx option on startup (also known as -Xmx) This is maximum size you should ever need in which cause you shouldn't need to set it to more than the maximum size you will ever need.
However, a work around is to have the main() check the maximum size and restart the java if the maximum size is not as desired. i.e. start another java program and die.
I asked same question to myself. And unlike answers above there is something I can do about my app increasing max heap JVM size. If app is a web server in cluster mode, I could start a new instance with changed min/max heap size and than shutdown initial instance. That shall be especially simple in GlassFish where you have management instance separated from nodeAgent(app server clustered instance) JVM.
Since many JVM applications are web apps, I think it worth to preserve in this blog.
If I understand your question correctly, you're trying to change the heap size at runtime. I don't see any reason why this should be possible. Set the heap size at startup using the -Xmx JVM option. I also advise you to set the -Xms option only if you absolutely need to. This option sets the initial amount of head memory that is allocated for the JVM.
You should know how your application behaves in terms of memory. Set the the value of -Xmx wisely. If your app is some kind of a server app you can set a higher value, otherwise compromise your choice with other possible apps running in client machines and of course available memory.