OutOfMemoryError with apache commons Base64 static method decodeBase64 - java

While decoding an Base64 encoded string to byte array (Have to do this as I have a key which can act on byte array to decrypt), I am getting outOfMemory. What are the effective ways to handle this problem? Should I chunk my input encoded String into partitions of size and then decode it or any other suggestions which are effective please suggest.
Code which was causing the issue.
byte[] encrypted = Base64.decodeBase64(strEncryptedEncodedData);
Stack Trace
DefaultQuartzScheduler_Worker-3
at java.lang.OutOfMemoryError.<init>()V (OutOfMemoryError.java:48)
at java.lang.StringCoding$StringEncoder.encode([CII)[B (StringCoding.java:300)
at java.lang.StringCoding.encode(Ljava/lang/String;[CII)[B (StringCoding.java:344)
at java.lang.String.getBytes(Ljava/lang/String;)[B (String.java:918)
at org.apache.commons.codec.binary.StringUtils.getBytesUnchecked(Ljava/lang/String;Ljava/lang/String;)[B (StringUtils.java:156)
at org.apache.commons.codec.binary.StringUtils.getBytesUtf8(Ljava/lang/String;)[B (StringUtils.java:129)
at org.apache.commons.codec.binary.BaseNCodec.decode(Ljava/lang/String;)[B (BaseNCodec.java:306)
at org.apache.commons.codec.binary.Base64.decodeBase64(Ljava/lang/String;)[B (Base64.java:669)
Eclipse Memory Analyzer memory usage:
Edit1: Max allowed XMX is 1 GB.
Edit2: JDK version"1.8.0_91"

try to increase max heap size to the JVM using option like this
-Xmx4096m

Please specify the java version you use for this code.
There are more than 10 different types of OutOfMemoryError as listed below and yours might be “10.java.lang.OutOfMemoryError: Direct buffer memory” type. Please verify your exception stack trace to find this matching string to confirm the same. If you see different type, please share it.
I verified that “java.lang.StringCoding$StringEncoder” class you shared in your exception trace uses java.nio.ByteBuffer and other related classes. You can validate the import sections in the below url.
http://cr.openjdk.java.net/~sherman/7040220/webrev/src/share/classes/java/lang/StringCoding.java.html
Java applications can access native memory (not heap memory) for buffer operations (direct byte) to perform speed operations. Some portion of memory is allocated to JVM from native memory for these direct byte buffer operations. If its size is not enough, you can increase it using VM flag –XX:MaxDirectMemorySize= (eg. -XX:MaxDirectMemorySize=10M). Increasing heap memory by using –Xmx flag would not solve this type of outofmemory. Please try MaxDirectMemorySize flag and see whether it solves your problem.
If you want to know more details about this OutOfMemoryError, you can read Java Performance Optimization: How to avoid the 10 OutOfMemoryErrors book.
1.java.lang.OutOfMemoryError: Java heap space
2.java.lang.OutOfMemoryError: Unable to create new native thread
3.java.lang.OutOfMemoryError: Permgen space
4.java.lang.OutOfMemoryError: Metaspace
5.java.lang.OutOfMemoryError: GC overhead limit exceeded
6.java.lang.OutOfMemoryError: Requested array size exceeds VM limit
7.java.lang.OutOfMemoryError: request "size" bytes for "reason". Out of swap space?
8.java.lang.OutOfMemoryError: Compressed class space
9.java.lang.OutOfMemoryError: "reason" "stack trace" (Native method)
10.java.lang.OutOfMemoryError: Direct buffer memory

Related

Java: How to optimize the Heap allocation & Garbage collection?

I have a spring batch application, it consumes ~16GB Memory & 75% of CPU(4core X2.5Ghz) and at times it throws out of memory exception.
I want to optimize the Heap allocation & Garbage collection and tried with the following JVM options so resolve the out of memory exception.
I could not understand some of these parameters as I copy pasted directly from an article
JAVA_OPTS="-server -Xmx20480m -Xms512m -XX:+UseConcMarkSweepGC
-XX:+UseParNewGC -XX:+CMSClassUnloadingEnabled -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=30 -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:ParallelCMSThreads=2 -XX:+UseCMSCompactAtFullCollection -XX:+DisableExplicitGC -XX:MaxHeapFreeRatio=70 -XX:MinHeapFreeRatio=40 -XX:MaxTenuringThreshold=0 -XX:NewSize=450m -XX:MaxNewSize=650m"
would it really optimize the Heap allocation & Garbage collection and resolve the out of memory exception.?
First, you need to take a heap dump of the process when it is throwing the OOM error. You can do that by adding -XX:+HeapDumpOnOutOfMemoryError JVM option. After when you have the heap dump try using any of the following tool to analyze your heap dump. Locate which object is growing in the memory and then optimize it. Heap dump analyze tools are :
Eclipse Memory Analyzer
Heap Hero
jxray
This error is usually thrown when there is insufficient space to allocate an object on the Java heap or if the Java process is spending more than 98% of its time doing garbage collection and if it is recovering less than 2% of the heap and has been doing so far the last 5 garbage collection cycles.
I would first use a Java profiler to determine what methods are allocating large numbers of objects on the heap and make sure that they are no longer referenced after they are not needed. If this doesn't fix the issue and I have confirmed that I need all the objects, the other option would be to increase the max heap size of the program.
This could also happen when you are using too many 'String' objects or updating those strings again and again.
Strings are stored in a hashed string pool, which resides in the Heap space. When you manipulate a string, a new string is formed and stored in a different pool (hashed pools) but the original string is not deleted until the garbage collector does it.
If we use StringBuilder or StringBuffer (both are mutable, unlike strings), the space is better utilised.
Read more about strings immutability and why stringbuilder should be preferred when you need a lot of string manipulations to be performed.
StringBuilder-StringBuffer-Strings in java
Why strings are immutable in java?

StringBuffer char[] appears to be out of bounds in heapdump

Following an OutOfMemoryError I processed the resultant heapdumps through IBM Support Assistant's 64bit memory analyzer ( J9 VM running on Websphere 7.0.23)
Several leak candidates were listed ( all system classloader related ) however one of these appears to indicate that a char[] initialised with a value of 256 in StringBuffer actually contains 77 million null characters.
The resultant heapdump analysis from the Support Assistant shows a char[77418987] # 0xc32*** \u0000\u0000\u0000.......
this is referenced by StringBuffer -> PatternLayout -> TimeAndSizeRollingAppender
The retained heap checks out, 2 bytes for each char and 18 for the array itself for a total of 150+ Mbs.
Log4j version is 1.2.16 and we use the simonsite TimeAndSizeRollingAppender ( though I would like to remove this dependency ).
Could this be a false positive from Support Assistant or is there some way in which a char[256] can become a char[77000000+] on the heap?
By default, WebSphere generates a PHD file in response to an OOM event. One thing you need to be aware of is that these dumps contain information about the objects in the heap and their references, but not the actual data stored in attributes and arrays (of primitive types). That's why the memory analyzer only shows zeros. To get more information about the root cause, you should configure your WebSphere to create a system dump. That will allow you to see the data in the array and should give you a hint about what is happening.
The following link explains how to do this:
http://pic.dhe.ibm.com/infocenter/isa/v4r1m0/topic/com.ibm.java.diagnostics.memory.analyzer.doc/producing.html
For the 256 vs. 77000000+ question: 256 is only the initial capacity of the StringBuffer. It grows automatically as needed when data is appended.

java heap memory usage exception when using FOR lOOP

When i run the below program i got the exception when for loop begins its execution at i=1031521. How to over come memory usage of this type?
class wwww
{
public static void main(String args[])
{
String abc[]=new String[4194304];
String wwf="";
int s_count=524286;
for(int i=0;i<4194304;i++)
{
System.out.println("----------enter--------"+i);
abc[i]=""+i;
System.out.println("----------exit--------"+i);
}
}
}
The exception is:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2882)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.
java:100)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:390
)
at java.lang.StringBuilder.append(StringBuilder.java:119)
at wwww.main(wwww.java:12)
This is because your your uses up all the heap space allocated to your jvm.
You can use argument while running the program to specify the heap size that you would like to allocate.
This is an example:
java -Xmx256m MyClass
Here a maximum of 256 MB of heap space will be allocated
How to over come memory usage of this type?
Don't perform memory usage of this type. You are creating 4194304 strings, of the general form ""+i. You don't need 4194304 strings of that form all at once. You only need one of them at a time, if any, and you can create it every time you need it.
You could either:
Increase the heap size that you give to your program. This is done via the -Xmx command-line argument to java.
Re-engineer the program to use less memory. Do you really need to keep all those strings in memory at once?

Does Immutability of Strings in Java cause Out Of Memory

I have written a simple Java program that reads a million rows from the Database and writes them to a File.
The max memory that this program can use is 512M.
I frequently notice that this program runs Out Of Memory for more than 500K rows.
Since the program is a very simple program it is easy to find out that this doesn't have a memory leak. the way the program works is that it fetches a thousand rows from the Database, writes them to a file using Streams and then goes and fetches the next thousand rows. The size of each row varies but none of the rows is huge. On taking a dump while the program is running the older string are easily seen on the heap. These String in heap are unreachable which means they are waiting to get Garbage collected. I also believe that the GC doesn't necessarily run during the execution of this program which leaves String's in the heap longer than they should.
I think the solution would be to use long Char Arrays(or Stringbuffer) instead of using String objects to store the lines that are returned by the DB. The assumption is that I can overwrite the contents of a Char Array which means the same Char Array can be used across multiple iterations without having to allocate new Space each time.
Pseudocode :
Create an Array of Arrays using new char[1000][1000];
Fill the thousand rows from DB to the Array.
Write Array to File.
Use the same Array for next thousand rows
If the above pseudocode fixes my problem then in reality the Immutable nature of the String class hurts the Java programmer as there is no direct way to claim the space used up by a String even though the String is no longer in use.
Are there any better alternatives to this problem ?
P.S : I didn't do a static analysis alone. I used yourkit profiler to test a heap dump. The dump clearly says 96% of the Strings have NO GC Roots which means they are waiting to get Garbage collected. Also I don't use Substring in my code.
Immutability of the class String has absolutely nothing to do with OutOfMemoryError. Immutability means that it cannot ever change, only that.
If you run out of memory, it is simply because the garbage collector was unable to find any garbage to collect.
In practice, it is likely that you are holding references to way too many Strings in memory (for instance, do you have any kind of collection holding strings, such as List, Set, Map?). You must destroy these references to allow the garbage collector to do its job and free up some memory.
The simple answer to this question is 'no'. I suspect you're hanging onto references longer than you think.
Are you closing those streams properly ? Are you intern()ing those strings. That would result in a permanent copy being made of the string if it doesn't exist already, and taking up permgen space (which isn't collected). Are you taking substring() of a larger string ? Strings make use of the flyweight pattern and will share a character array if created using substring(). See here for more details.
You suggest that garbage collection isn't running. The option -verbose:gc will log the garbage collections and you can see immediately what's going on.
The only thing about strings which can cause an OutOfMemoryError is if you retain small sections of a much larger string. If you are doing this it should be obvious from a heap dump.
When you take a heap dump I suggest you only look at live objects, in which case any retained objects you don't need is most likely to be a bug in your code.

OutOfMemoryError while doing docx comparison using docx4j

in my application i am comparing two docx files and creating one html comparison file, when i tried with below 150 or 170 lines of file then there is no issue, while i try to compare the big files like 200 lines or more than that then that time it showing the
java.lang.OutOfMemoryError: Java heap space error,
can any one please help on this?
You are running out of memory because you aren't using the Docx4jDriver class, which makes the diff problem more tractable by doing a paragraph level diff first.
Use it like so:
Body newerBody = ((Document)newerPackage.getMainDocumentPart().getJaxbElement()).getBody();
Body olderBody = ((Document)olderPackage.getMainDocumentPart().getJaxbElement()).getBody();
// 2. Do the differencing
java.io.StringWriter sw = new java.io.StringWriter();
Docx4jDriver.diff( XmlUtils.marshaltoW3CDomDocument(newerBody).getDocumentElement(),
XmlUtils.marshaltoW3CDomDocument(olderBody).getDocumentElement(),
sw);
// 3. Get the result
String contentStr = sw.toString();
System.out.println("Result: \n\n " + contentStr);
Body newBody = (Body) org.docx4j.XmlUtils
.unmarshalString(contentStr);
you can make the heap space bigger with -Xmx and -Xmx as VM Arguments
Here more about Heap Size Tuning or here Heap size
Try increasing the Java heap size using the command line arguments -Xmx<maximum heap size> and -Xms<minimum heap size>.
Also in your code, test that you actually have increased the heap size with the following:
long heapSize = Runtime.getRuntime().totalMemory();
System.out.println("Heap Size = " + heapSize);
Do this before calling Differencer.diff on line 117.
Try profiling your application rather than making assumptions or intelligent guess. You can use visualvm or console that ships with the Jdk.
Also, you can take a heap dump of your application using jmap and then use either jhat or eclipse mat (I prefer this, google it out) to see what's consuming the memory and look out for any unusual behavior.

Categories