DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • JVM Memory Architecture and GC Algorithm Basics
  • All You Need To Know About Garbage Collection in Java
  • Difference Between InitialRAMPercentage, MinRAMPercentage, MaxRAMPercentage
  • Heap Memory In Java Applications Performance Testing

Trending

  • The Future of Java and AI: Coding in 2025
  • Implementing Explainable AI in CRM Using Stream Processing
  • Distributed Consensus: Paxos vs. Raft and Modern Implementations
  • Useful System Table Queries in Relational Databases
  1. DZone
  2. Coding
  3. Java
  4. 7 JVM Arguments of Highly Effective Applications

7 JVM Arguments of Highly Effective Applications

By 
Ram Lakshmanan user avatar
Ram Lakshmanan
DZone Core CORE ·
Mar. 25, 20 · Tutorial
Likes (43)
Comment
Save
Tweet
Share
52.7K Views

Join the DZone community and get the full member experience.

Join For Free

At the time (March 2020) of writing this article, there are 600+ arguments that you can pass to JVM just around garbage collection and memory. If you include other aspects, the number of JVM arguments will easily cross 1000+. It’s way too many arguments for anyone to digest and comprehend. In this article, we will highlight seven important JVM arguments that you may find useful.

1. -Xmx and -XX:MaxMetaspaceSize

-Xmx is probably the most important JVM argument. -Xmx defines the maximum amount of heap size you are allocating to your application. (To learn about different memory regions in a JVM, you may watch this short video clip). You can define your application’s heap size like this:

Java
xxxxxxxxxx
1
 
1
-Xmx2g


Heap size plays a critical role in determining your:

a. Application performance.

b. Bill, that you are going to get from your cloud provider (AWS, Azure, etc.)

This brings up the question, what is the right heap size for my application? Should I allocate a large heap size or small heap size for my application? The answer is: "It depends." In this article, we have shared our thoughts on whether you need to go with large or small heap size.

Metaspace is the region where JVM’s metadata definitions, such as class definitions, method definitions, will be stored. By default, the amount of memory that can be used to store this metadata information is unlimited (i.e. limited by your container or machine’s RAM size). You need to use: XX:MaxMetaspaceSize argument to specify an upper limit on the amount of memory that can be used to store metadata information.

Java
xxxxxxxxxx
1
 
1
-XX:MaxMetaspaceSize=256m


2. GC Algorithm

As of March 2020, there are 7 different GC algorithms in OpenJDK:

  1. Serial GC.
  2. Parallel GC.
  3. Concurrent Mark and Sweep GC.
  4. G1 GC.
  5. Shenandoah GC.
  6. Z GC.
  7. Epsilon GC.

If you don’t specify the GC algorithm explicitly, then JVM will choose the default algorithm. Until Java 8, Parallel GC is the default GC algorithm. Since Java 9, G1 GC is the default GC algorithm.

The selection of the GC algorithm plays a crucial role in determining the application’s performance. Based on our research, we are observing excellent performance results with the Z GC algorithm. If you are running with JVM 11+, then you may consider using the Z GC algorithm (i.e. -XX:+UseZGC). More details about the Z GC algorithm can be found here.

The following table summarizes the JVM argument that you need to pass to activate each type of Garbage Collection algorithm.

GC Algorithm JVM argument
Serial GC -XX:+UseSerialGC
Parallel GC -XX:+UseParallelGC
Concurrent Market & Sweep (CMS) GC -XX:+UseConcMarkSweepGC
G1 GC -XX:+UseG1GC
Shenandoah GC -XX:+UseShenandoahGC
Z GC -XX:+UseZGC
Epsilon GC -XX:+UseEpsilonGC

3. Enable GC Logging

Garbage Collection logs contain information about Garbage Collection events, memory reclaimed, pause time duration, etc. You can enable the garbage collection log by passing following JVM arguments:

From JDK 1 to JDK 8:

Shell
xxxxxxxxxx
1
 
1
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:{file-path}


From JDK 9 and above:

Java
xxxxxxxxxx
1
 
1
-Xlog:gc*:file={file-path}


Example:

Java
xxxxxxxxxx
1
 
1
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/opt/workspace/myAppgc.log 
2
-Xlog:gc*:file=/opt/workspace/myAppgc.log


Typically, GC logs are used for tuning garbage collection performance. However, GC logs contain vital micro metrics. These metrics can be used for forecasting an application’s availability and performance characteristics.

In this article, we would like to highlight one such micrometric: ‘GC Throughput‘ (to read more on other available micrometrics, you may refer to this article). GC Throughput is the amount of time your application spends in processing customer transactions verse the amount of time it spends in processing GC activities. If your application’s GC throughput is 98%, then it means your application is spending 98% of its time in processing customer activity, and the remaining 2% is spent in GC activity.

Now, let’s look at the heap usage graph of a healthy JVM:
Healthy JVM’s heap usage graph (generated by https://gceasy.io)

Healthy JVM’s heap usage graph (generated by https://gceasy.io)

You can see a perfect saw-tooth pattern. You can notice that when Full GC (red triangle) runs, memory utilization drops all the way to bottom.

Now, let’s look at the heap usage graph of a sick JVM:
Sick JVM’s heap usage graph (generated by https://gceasy.io)

Sick JVM’s heap usage graph (generated by https://gceasy.io)

You can notice towards the right end of the graph, even though GC repeatedly runs, memory utilization isn’t dropping. It’s a classic indication that the application is suffering from some sort of memory problem.

If you take a closer look at the graph, you will notice that repeated full GC’s started to happen right around 8 am. However, the application starts to get an OutOfMemoryError only around 8:45 am. Till 8 am, the application’s GC throughput was about 99%. 

But right after 8 am, GC throughput started to drop down to 60%. Because, when repeated GC runs, the application wouldn’t be processing any customer transactions and it will only be doing GC activity. As a proactive measure, if you notice GC throughput starting to drop, you can take out the JVM from the load balancer pool. So that unhealthy JVM will not process any new traffic. It will minimize customer impact.
Repeated Full GC happens way before OutOfMemoryError

Repeated Full GC happens way before OutOfMemoryError

You can monitor GC related micrometrics in real-time using GCeasy REST API.

4. -XX:+HeapDumpOnOutOfMemoryError, -XX:HeapDumpPath

OutOfMemoryError is a serious problem that will affect your application’s availability/performance SLAs. To diagnose OutOfMemoryError or any memory-related problems, one would have to capture the heap dump right at the moment or few moments before the application starts to experience OutOfMemoryError. 

As we don’t know when OutOfMemoryError will be thrown, it’s hard to capture the heap dump manually at the right around the time. However, capturing heap dumps can be automated by passing following JVM arguments:

-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath={HEAP-DUMP-FILE-PATH}  

In -XX:HeapDumpPath, you need to specify the file path where heap dump should be stored. When you pass these two JVM arguments, heap dumps will be automatically captured and written to a defined file path, when OutOfMemoryError is thrown. Example:

Java
xxxxxxxxxx
1
 
1
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/crashes/my-heap-dump.hprof


Once heap dumps are captured, you can use tools like HeapHero or  EclipseMAT to analyze heap dumps.

More details around the OutOfMemoryError JVM arguments can be found in this article.

5. -Xss

Each application will have tens, hundreds, thousands of threads. Each thread will have its own stack. In each thread’s stack following information are stored:

  • Methods/functions that are currently executed.
  • Primitive datatypes.
  • Variables.
  • Object pointers.
  • Return values.

Each one of them consumes memory. If their consumption goes beyond a certain limit, then a StackOverflowError is thrown. More details about StackOverflowError and solutions to resolve it can be found in this article. However, you can increase the thread’s stack size limit by passing the -Xss argument. Example:

Shell
xxxxxxxxxx
1
 
1
-Xss256k


If you set this -Xss value to a huge number, then memory will be blocked and wasted. Suppose you are assigning -Xss value to be 2mb whereas, it needs only 256kb, then you will end up wasting a huge amount of memory, not just 1792kb (i.e. 2mb – 256kb). Do you wonder why?

Say your application has 500 threads, then with -Xss value to be 2mb, your threads will be consuming 1000mb of memory (i.e. 500 threads x 2mb/thread). On the other hand, if you've only allocated -Xss to be 256kb, then your threads will be consuming only 125mb of memory (i.e. 500 threads x 256kb/thread). You will save 875mb (i.e. 1000mb – 125mb) of memory per JVM. Yes, it will make such a huge difference.

Note: Threads are created outside of the heap (i.e. -Xmx), thus this 1000mb will be in addition to the -Xmx value you have already assigned. To understand why threads are created outside the heap, you can watch this short video clip.

Our recommendation is to start from a low value (say 256kb). Run thorough regression, performance, and AB testing with this setting. Only if you experience a StackOverflowError should you increase the value; otherwise consider sticking to a low value. 

6. -Dsun.net.client.defaultConnectTimeout and -Dsun.net.client.defaultReadTimeout

Modern applications use numerous protocols (i.e. SOAP, REST, HTTP, HTTPS, JDBC, RMI, etc.) to connect with remote applications. Sometimes remote applications might take a long time to respond. Sometimes they may not respond at all.

If you don’t have proper timeout settings, and if remote applications don’t respond fast enough, then your application threads/resources will get stuck. Remote applications unresponsiveness can affect your application’s availability. It can bring down your application to a grinding halt. To safeguard your application’s high availability, appropriate timeout settings should be configured.

You can pass these two powerful timeout networking properties at the JVM level that can be globally applicable to all protocol handlers that uses java.net.URLConnection:

  1. sun.net.client.defaultConnectTimeout specifies the timeout (in milliseconds) to establish the connection to the host. For example, for HTTP connections, it is the timeout when establishing the connection to the HTTP server.
  2. sun.net.client.defaultReadTimeout specifies the timeout (in milliseconds) when reading from the input stream when a connection is established to a resource.

Example, if you would like to set these properties to 2 seconds:

Shell
xxxxxxxxxx
1
 
1
-Dsun.net.client.defaultConnectTimeout=2000 -Dsun.net.client.defaultReadTimeout=2000


Note: By default, values for these two properties are -1, which means no timeout is set. More details on these properties can be found in this article.

7. -Duser.timeZone

Your application might have sensitive business requirements around time/date. For example, if you are building a trading application, you can’t take a transaction before 9:30 am. To implement those time/date related business requirements, you might be using java.util.Date or java.util.Calendar objects. 

These objects, by default, pick up time zone information from the underlying operating system. This will become a problem if your application is running in a distributed environment. Take a look at the following scenarios:

  • If your application is running across multiple data centers, say, San Francisco, Chicago, Singapore – then JVMs in each data center would end up having a different time zone. Thus, JVMs in each data center would exhibit different behaviors. It would result in inconsistent results.
  • If you are deploying your application in a cloud environment, applications could be moved to different data centers without your knowledge. In that circumstance also, your application would end up producing different results.
  • Your own Operations team can also change the time zone without bringing to the development team’s knowledge. It would also skew the results.

To avoid these commotions, it’s highly recommended to set the time zone at the JVM using the  Duser.timezone system property. For example, if you want to set EDT time zone for your application, you would do:

Java
xxxxxxxxxx
1
 
1
-Duser.timezone=US/Eastern

Conclusion

In this article, we have attempted to summarize some of the important JVM arguments and their positive impacts. We hope you may find it helpful.

Java (programming language) Java virtual machine application garbage collection

Opinions expressed by DZone contributors are their own.

Related

  • JVM Memory Architecture and GC Algorithm Basics
  • All You Need To Know About Garbage Collection in Java
  • Difference Between InitialRAMPercentage, MinRAMPercentage, MaxRAMPercentage
  • Heap Memory In Java Applications Performance Testing

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!