Limiting JVM on VPS (Virtual Private Server)

Friday Aug 31st 2007 by Serge Bornow
Share:

It can be difficult to set up and run Java (JVM) on a Virtual Private Server. If you get past the initial steps, you will see that it is well worth your effort.

What Are Virtual Private Servers?

Virtual Private Servers are the most advanced and affordable solution for anyone wanting to run their own server. They are used to partition a single physical server into many isolated virtual private servers. Each virtual private server looks and behaves exactly like a real networked server system, complete with its own set of init scripts, users, processes, and file systems. There is one downside to VPS: running Java on it. JVM only sees the computer as it is, 16Gigabytes of RAM and if you are attempting to start up an Application Server, JVM will happily attempt to reserve, say, 2 gigabytes and will not be able to do so in a 512 megabyte account. How can you get around this?

VPS is definitely an affordable choice of running a J2EE server or even a Java Container such as Tomcat (for those that have less than 512 Mb). Unlike the Private Server where you are the master of domain and all the CPU power as well as all of the RAM available belongs to you, VPS shares the CPU, RAM, and other space with other users (although not as many as on Shared Hosting).

The Problem

There are problems allocated to this case with JVM. Java Virtual Machine is not capable of understanding that you are using a virtual operating system with specific limits allocated specifically for your account.

How do you solve the problem of using JVM on a VPS?

In most cases, be that a J2EE App. server like JBoss or something else, if you do not explicitly tell the JVM to limit its consumption of RAM, JVM will attempt to gather a default (if available, for that product) value and use thatt as its limit. For example, Sun's open source Application Server Glassfish has a default requirement of 512 Mb of ram and would throw the following:

[blah@blah]# java -jar glass*jar -console
Exception in thread "main" java.lang.OutOfMemoryError
   at java.lang.ClassLoader.defineClass1(Native Method)
   at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
   at java.security.SecureClassLoader.defineClass
      (SecureClassLoader.java:124)
   at java.net.URLClassLoader.defineClass
      (URLClassLoader.java:260)
   at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
   at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
   at sun.misc.Launcher$AppClassLoader.loadClass
      (Launcher.java:268)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
   at java.lang.ClassLoader.loadClassInternal
      (ClassLoader.java:319)

Even if you specify java -Xmx256m -jar glass*jar -console, JVM will not obey to run all involved JARs with the parameter -Xmx256m. In fact, in this case you are limited to 256 Mb of ram to just running that JAR.

As suggested, if you have over 512 Mb of RAM, you will have no problem installing Glassfish on a VPS server: java -Xmx512m -jar glass*jar -console.

Another type of exception may look like this:

Exception in thread "main" java.io.IOException: java.io.IOException:
Cannot allocate memory
   at java.lang.UNIXProcess.<init>(UNIXProcess.java:148)
   at java.lang.ProcessImpl.start(ProcessImpl.java:65)
   at java.lang.ProcessBuilder.start(ProcessBuilder.java:451)
   at java.lang.Runtime.exec(Runtime.java:591)
   at java.lang.Runtime.exec(Runtime.java:464)

The above exception is applicable to *Nix-based operating systems.

Another quite interesting behavior is that JVM may be able to run whatever it is you want but might not be capable of deallocating the resource you took and you will receive this:

Java HotSpot(TM) Client VM warning: Attempt to deallocate stack
                                    guard pages failed.
Java HotSpot(TM) Client VM warning: Attempt to allocate stack guard
                                    pages failed.

The Solution

The solutions that I found through numerous attempts and failures are the following:

1. Limit the RAM for JBoss Application Server

Locate the runnable script RUN.SH in the $JBOSS_HOME/bin directory. Edit this file and explicitly add -Xmx and/or -Xms.

Please remember that, even if you have 512 MB of RAM on your VPS, you will not be able to specify -Xmx500m and expect it to use just 500 megs of RAM.

Please adjust accordingly and start from -Xmx32m. You will see that your JBoss will be able to start even if you have just 128 megs of RAM on your account.

2. Use wide settings because it's a local variable

Tested on RedHat Fedora Linux, I have been able to force the JVM to pick up the limits like this:

_JAVA_OPTIONS='-Xmx128m'
export _JAVA_OPTIONS

This special variable that MUST have an underscore in front will force the JVM to obey the limits and run whatever you want. Beware, however, that this limit is global for the user and all calls: java -version will always use these EXPLICIT options.

3. A tricky way

You also could create an executable script on your *NIX account and in it call the Java command with appropriate options. The content of the file may be something like this:

#!/bin/sh
exec /usr/java/jdk1.6.0/bin/java -Xmx64m "$@"

4. Another trick

alias java='java -Xms32m -Xmx128m'

On *Nix systems, this alias would work just fine.

Up to this point, you should be able to find a solution that would let you run JVM within your VPS Hosting account. Below you will find a crucial difference between two important options for a JVM. Remember that when JVM evaluates the system on which is resides and finds out that RAM exceeds 2 gigabytes, it assumes that your system is a server for its use and will assume the option -Server.

java -server versus java –client

Sun's document on Java Hot Spot states:

J2SE 5.0 provides two implementations of the HotSpot Java virtual machine (JVM):

  • The client VM is tuned for reducing startup time and memory footprint. Invoke it by using the -client JVM command-line option.
  • The server VM is designed for maximum program execution speed. Invoke it by using the -server JVM command-line option.

By default, the Application Server uses the JVM setting appropriate to the purpose:

  • Platform Edition, targeted at application developers, uses the -client JVM flag to optimize startup performance and conserve memory resources.
  • Enterprise Edition, targeted at production deployments, uses the default JVM startup mode. With J2SE 5.0, the HotSpot VM provides server-class machine detection, which will use the server VM if it detects "server-class" hardware (at least two CPUs and 2 Gb of physical memory).

This is quite important because VPS servers are usually fully loaded with at 8 Gb of RAM or more to cater to more users on a single machine; therefore, JVM is quite happy with those numbers.

Fortunately, there are many different virtualization applications on the market, both commercial and open source, and provide different ways to configure the limits for each account; therefore, the JVM would not be able to detect such limits and assume default values.

Limiting Ant's Use of RAM

ANT is a neat and most popular build tool and is commonly used. Glassfish utilizes ANT as a way to install itself. You will be pleased to hear that you can limit its use of memory by using this variable:

ANT_OPTS=-Xmx64m

Conclusion

VPS hosting is the optimal and most affordable way to host your J2EE application, yet it isn't very easy to initially set up JVM to work as you wanted. The final result will be worth the effort.

Helpful Links

About the Author

Serge's picture

Serge Bornow works as a freelance consultant in J2EE and .NET.

His main interests are most current open source projects in J2EE, Ajax, and web development. He also plays tennis and enjoys traveling around the world.

Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved