Sometimes java applications take more than the default allocated amount of memory that is provided to the Java Virtual Machine (JVM).  It's important to note that just because your computer has 2 GB of RAM, java will only ever use what it's told it can.  By default a java process allocates 256MB of RAM, often times this is not enough and must be increased.  Otherwise you will likely see an error message/exception that looks similar to this:

"java.lang.OutOfMemoryError: Java heap space"

The JVM has many "pools" of memory.  The "heap" is one of those pools of memory.  In a way these different pools of memory are modeled similar to short and long term memory in people.  In that data in the "short term memory" often contains garbage that you don't need to remember.  Things that are useful to remember are moved from the short term memory to the long term memeory.

When you start up java,  it allocates memory to the JVM by the "heap size" setting.  You can change these settings when you start java by passing additional command line arguments to the java process when it start.

For example by default you would start MyRobotLab like this

java -jar myrobotlab.jar

However, lets say you want to give MyRobotLab 2 GB of ram when you start it up so you avoid the "OutOfMemoryError", you can do this by specifying the java parameter  "-Xmx" and passing it the desired memory allocation in a format like  256m  (for 256 megabytes of ram) or 2g  (for 2 gigabytes of ram) 

the full command would then look like this:

java -Xmx2g -jar myrobotlab.jar

When the JVM starts up, it will allocated up to 2gb of ram to the java application before throwing the dreaded OutOfMemoryError.

 

Now, there is another type of memory pool called the "permenent generation" memory, or more commonly known as PermGen.  If you see an error message like this, it means that you're out of a different "pool" of memory 

 

java.lang.OutOfMemoryError: PermGen space

 

The "PermGen" memory is where Java loads all of the Jar files.  When a java process starts up, all of the Jar files in the class path are loaded into the PermGen memory space (I believe this is a lazy load, someone with more knowledge of the JVM internals can correct me on this.)  If there are a lot of JAR files to load, it's possible that you could run out of PermGen memory, and this means you need to increase the PermGen memory size.  That can be done with the "-XX:MaxPermSize="

By default,  I think 128MB of ram is allocated to the PermGen memory space.  To increase this you can add the commnad line argument to java to increase it as folows:

java -XX:MaxPermSize=512m -jar myrobotlab.jar

This would allocate additional memory for loading additional jar files and libraries into MRL.

The topic of JVM memory settings and Garbage Collection Tuning are quite expansive, for brevity,  I have included the key commands to increase the settings.  There are tuning parameters for how large the pools are and how objects get moved from the "short term" or "early generation" pools into the "long term" or "older generation" memory pools.

Hope this info was useful, happy roboting!

 

GroG

7 years 7 months ago

Great post Kwatters !

From my personal experience I have found default dependent on JVM & OS ..  sometimes the default I've found as low as 64 Mb.

At the moment your recommendation I don't think will give the desired results, as

java -Xmx2g -jar myrobotlab.jar

gets passed to the Agent Service and not Runtime Service.
 

The Agent Service is responsible for constructing the more complex command line for myrobotlab to work.  It spawns the final process with pathing for JNA & JNI, adds additional libraries on the classpath, and sets other environmental variables set depending on operating system.  To do specify "java -Xmx2g -jar myrobotlab.jar" will just give the memory to the process which starts myrobotlab, not myrobotlab itself.

If you want 2Gigs for myrobotlab the easiest way would be to look in the log for the command line (it's (used to be) printed out and add the additional -Xmx2g parameters)

Which might look like this:

java -Xmx2g -Djava.library.path=libraries/native -cp ./myrobotlab.jar:./libraries/jar/*.jar org.myrobotlab.service.Runtime -service gui GUIService python Python webgui WebGui

I have not tried it as I currently don't have any 'real' hardware which is not currently broken ;)

 

 

Hmm... ok. so I think we need to handle additional opts passed in when you start the MRL agent and pass those through to the spawned process.

I think we should keep it simple and generic here.  We can add an additional command line arg that the agent will additionall pass down through to the spawned MyRobotLab java process... 

maybe something like: 

-java.opts="-Xmx2g -Dfoo.bar=baz ...etc.."    

?

Ya .. that might be nice .. also needs a default way of how we want the Agent to behave (and I know its current behavior is not what we want) ..

I went one way (Agent up all the time - streams all the logging from all other process(es) - never dies) 

to

Dies as soon as new process starts...

Should probably be somewhere in the middle.

ie. should stay around until all processes it spawned are dead (then immediately dies) & streams all process io to std out

bcarroll

7 years 4 months ago

creating an environment variable name _JAVA_OPTIONS can be used to adjust the java JVM options globally.  Every java process that is involved from that shell will have those settings.

Windows:
set _JAVA_OPTIONS=-Xmx2g

Linux:
export  _JAVA_OPTIONS=-Xmx2g