Countermeasures for Java OutOfMemoryError

Basically, it is necessary to investigate and analyze with gcviewer-1.36 or Memory Analyzer to identify the cause. In my case, I need to save a large object every second, and I get an error in less than an hour.

Countermeasure:

1. Add VM memory (if necessary)

startup_parameters.sh


appserver_mem="6000m"
appserver_java_opt="-Xms=3074m -Xmx=3074m -XX:PermSize=1024m -XX:MaxPermSize=1024m -XX:NewSize=1024m -XX:MaxNewSize=1024m  -server -Djava.awt.headless=true"

2. By flyingweight to the source, in the case of the same String or object, it will be saved in the memory as one.

flyweight core class

FlyweightPool.java


package util;

import java.lang.ref.WeakReference;
import java.util.WeakHashMap;

public class FlyweightPool<T> {

    private WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<>();
    public FlyweightPool() {}


    public T flyweightOf(T obj) {
        if (obj == null) {
            return null;
        }
        synchronized(pool) {
            WeakReference<T> w = pool.get(obj);
            T flyweihgt = (w == null ? null : w.get());
            if (flyweihgt != null) {
                return flyweihgt;
            }
            pool.put(obj, new WeakReference<T>(obj));
            return obj;
        }
    }

    public boolean contains(T obj) {
        synchronized (pool) {
            return pool.containsKey(obj);
        }
    }

    public void remove(T obj) {
        synchronized (pool) {
            pool.remove(obj);
        }
    }
}

flyweight implementation class

TsunamiBinaryPointBean.java


    private static final FlyweightPool<List<TsunamiBinaryFauldBean>> listFlyweights = new FlyweightPool<>();
    private static final FlyweightPool<TsunamiBinaryFauldBean> dataFlyweight = new FlyweightPool<>();

    /**
     *Set the point ID
     */
	public void setPointID(String pointID){
		this.pointID = StringUtil.flyweightOf(pointID);
	}

    /**
     *Memory tuning, flyweight objects
     */
    public void optimizeMemory() {
        List<TsunamiBinaryFauldBean> fauldBean;
        synchronized(this.tsunamiBinaryFaulds) {
        	TsunamiBinaryFauldBean[] dataArr = new TsunamiBinaryFauldBean[this.tsunamiBinaryFaulds.size()];
            for (int i = 0; i < this.tsunamiBinaryFaulds.size(); i++) {
                dataArr[i] = dataFlyweight.flyweightOf(this.tsunamiBinaryFaulds.get(i));
            }
            fauldBean = listFlyweights.flyweightOf(Arrays.asList(dataArr));
        }
        this.tsunamiBinaryFaulds = fauldBean;
    }

3. Still useless, save it in memory as a compressed binary instead of an object

compression

XXX.java


    public static ByteBuffer compress(ByteBuffer buffer){
        ByteArrayOutputStream compressBaos = new ByteArrayOutputStream();
        GZIPOutputStream gzip = null;
        try{
            gzip = new GZIPOutputStream(compressBaos) {{
                def.setLevel(Deflater.BEST_COMPRESSION);
             }};
            gzip.write(buffer.array());
            gzip.finish();
            gzip.flush();
            compressBaos.flush();
            
            byte[] compressed = compressBaos.toByteArray();
            return ByteBuffer.wrap(compressed);
        }catch(IOException e){
        	DonetLogger.LOGGER.error(1,"ByteBuffer compression", "An error has occurred.", e);
        	return null;
        }finally{
        	try{
        		if(gzip != null){
        			gzip.close();
        		}
        	}catch(Exception e){}
        	try{
        		if(compressBaos != null){
        			compressBaos.close();
        		}
        	}catch(Exception e){}
        	gzip = null;
        	compressBaos = null;
        }
    }

Defrost

XXX.java


public static ByteBuffer decompress(ByteBuffer buffer){
        ByteArrayOutputStream decompressBaos = new ByteArrayOutputStream();
        GZIPInputStream gzip = null;
        byte[] b = new byte[1024*100];
        try{
            gzip = new GZIPInputStream(new ByteArrayInputStream(buffer.array()));
            for (int read = gzip.read(b); read >= 0; read = gzip.read(b)) {
            	decompressBaos.write(b, 0, read);
            }
            decompressBaos.flush();
            byte[] decompressed = decompressBaos.toByteArray();
            return ByteBuffer.wrap(decompressed);
        }catch(IOException e){
        	DonetLogger.LOGGER.error(1,"ByteBuffer decompression", "An error has occurred. Check the accuracy of ByteBuffer.", e);
        	return null;
        }finally{
        	try{
        		if(gzip != null){
        			gzip.close();
        		}
        	}catch(Exception e){}
        	try{
        		if(decompressBaos != null){
        			decompressBaos.close();
        		}
        	}catch(Exception e){}
        	gzip = null;
        	decompressBaos = null;
        }
    }

Binary output

XXX.java


    public void binaryWrite(DataOutputStream output) throws IOException{
    	if(this.getPointCount() <= 0){
    		return;
    	}
		output.writeUTF(this.header);
		output.writeUTF(toSimpleDateTimeString(this.tsunamiDatetime));
		output.writeShort(pointCount);
    	for(TsunamiBinaryPointBean point :tsunamiBinaryPoints){
    		output.writeUTF(point.getAreaID());
    		output.writeUTF(point.getPointID());
    		output.writeFloat(point.getLineAbsAverage());
    		output.writeShort(point.getFauldCount());
    		output.writeFloat(point.getFirstLineAbsAverage());
        	for(int i=0; i<point.getTsunamiBinaryFaulds().length; i++){
        		output.writeUTF(point.getTsunamiBinaryFaulds()[i].getFauldID());
        		output.writeUTF(point.getTsunamiBinaryFaulds()[i].getStartDatetime());
        		output.writeFloat(point.getTsunamiBinaryFaulds()[i].getAmplificationFactor());
        		output.writeFloat(point.getTsunamiBinaryFaulds()[i].getFauldAbsAverageValue());
        	}
    	}
	    output.flush();
    }

Binary reception What is output by DataOutputStream is only received by DataInputStream, and in other cases it becomes an unintended operation.

XXX.java


   public static ByteBuffer toByteBuffer(DataInputStream input){
    	ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    	DataOutputStream out = new DataOutputStream(buffer);
    	byte[] result;
    	try{
	    	out.writeUTF(input.readUTF());
			out.writeUTF(input.readUTF());
			int point = input.readShort();
			out.writeShort(point);
			for(int i=0;i<point;i++){
				out.writeUTF(input.readUTF());
				out.writeUTF(input.readUTF());
				out.writeFloat(input.readFloat());
				int fauld = input.readShort();
				out.writeShort(fauld);
				out.writeFloat(input.readFloat());
				for(int j=0;j<fauld;j++){
					out.writeUTF(input.readUTF());
					out.writeUTF(input.readUTF());
					out.writeFloat(input.readFloat());
					out.writeFloat(input.readFloat());
				}
			}
			result = buffer.toByteArray();
			return ByteBuffer.wrap(result);
		}catch(IOException e){
			return null;
		}finally{
	        try {
	            if (out != null) {
	            	out.close();
	            }
	        }catch (IOException e) {}
	        try {
	            if (buffer != null) {
	            	buffer.close();
	            }
	        }catch (IOException e) {}
	    	buffer = null;
	    	out = null;
		}
    }

Recommended Posts

Countermeasures for Java OutOfMemoryError
For JAVA learning (2018-03-16-01)
2017 IDE for Java
java error countermeasures
Java for statement
[Java] for statement, while statement
[Java] Package for management
[Java] for statement / extended for statement
NLP for Java (NLP4J) (2)
(Memo) Java for statement
NLP for Java (NLP4J) (1)
Java Gold Countermeasures: Format
Java Gold Countermeasures: Localization
VSCode Java Debugger for Java Build failed Causes and countermeasures
Java update for Scala users
Java debug execution [for Java beginners]
[Java] Basic statement for beginners
[Java] Precautions for type conversion
Books used for learning Java
2018 Java Proficiency Test for Newcomers-Basics-
Java thread safe for you
[Java] Summary of for statements
Java for beginners, data hiding
[Java] Tips for writing source
Java installation location for mac
Java application for beginners: stream
Java while and for statements
C # cheat sheet for Java engineers
New grammar for Java 12 Switch statements
[For beginners] Summary of java constructor
AWS SDK for Java 1.11.x and 2.x
Rock-paper-scissors game for beginners in Java
Java for beginners, expressions and operators 1
[Java] Memo for naming class names
[For beginners] Run Selenium in Java
Hello World for ImageJ Java Plugin
[OpenCV3.2.0] Eclipse (Java) settings (for Mac)
Java for beginners, expressions and operators 2
Enable OpenCV with java8. (For myself)
Spring Framework tools for Java developer
java (use class type for field)
Build Java development environment (for Mac)
Java
[Java & SpringBoot] Environment Construction for Mac
Settings for SSL debugging in Java
Generics of Kotlin for Java developers
Java
Diary for Java SE 8 Silver qualification
[For Java beginners] About exception handling
Classes and instances Java for beginners
Modern best practices for Java testing
GraalVM for Java Performance (Windows Developer Build)
Implementation of clone method for Java Record
[Until March 5, 2020] Renew RDS certificate for java
Getting Started with Ruby for Java Engineers
[Java Spring MVC] Controller for development confirmation
Memory measurement for Java apps using jstat
Introduction to java for the first time # 2
Countermeasures for FDclone build failure on CentOS 8
First steps for deep learning in Java
Java for All! I read everyone's Java #minjava