简体   繁体   English

Java 8完整GC和OutOfMemory Java堆空间

[英]Java 8 full GC and OutOfMemory Java heap space

Using VisualVM and checking Tomcat 8.5 catalina.out log I see that almost every time (7 out of 11 times or so) when full GC happens logs show OutOfMemory (at the exact same minute). 使用VisualVM并检查Tomcat 8.5 catalina.out日志我发现,当发生完全GC时, 几乎每次(11次中的7次)日志都会显示OutOfMemory (在同一分钟)。

With Tomcat parameters that have something to do with memory management: -Xms3G -Xmx=6G -XX:+UseG1GC -XX:+UseStringDeduplication -XX:MaxHeapFreeRatio=100 与与内存管理有关的Tomcat 参数-Xms3G -Xmx = 6G -XX:+ UseG1GC -XX:+ UseStringDeduplication -XX:MaxHeapFreeRatio = 100

At first I thought that it was because of default -XX:MaxHeapFreeRatio value which is 70 since I saw that max. 起初我以为是因为-XX:MaxHeapFreeRatio的默认值是70,因为我看到了这个最大值。 heap size (and used heap of course) would drop significantly during full GC - to ~10-20% . 完全GC期间,堆大小(当然也包括用过的堆)将显着下降- 约10-20% However adding XX:MaxHeapFreeRatio=100 did not fix it. 但是,添加XX:MaxHeapFreeRatio = 100不能解决该问题。

Although this is memory usage graph with different set of JVM parameters (can not get the one with old JVM parameters ATM) it is similar in a way after full GC memory usage grows rapidly , same max. 尽管这是具有不同 JVM参数集的内存使用情况图 (无法使用旧的JVM参数ATM获得),但在满GC内存使用量迅速增长之后,其方式类似,最大值相同。 heap size and that max. 堆大小和最大 heap size does not drop. 堆大小不会减少。

在此处输入图片说明

Any ideas why this could happen? 任何想法为什么会发生这种情况?

Update: I forgot to mention that previously full GC and OutOfMemory would happen when heap size was not even full - ~5GB. 更新:我忘了提一下,当堆大小甚至 不满-〜5GB时,就会发生以前的完整GCOutOfMemory Back then not a single time did I see heap reach 6GB. 那时,我没有一次看到堆达到6GB。

Obviously some of the objects created cannot be garbage collected properly. 显然,创建的某些对象无法正确地进行垃圾回收。 You can try to use sampler function of VisualVM and track the number of instances created. 您可以尝试使用VisualVM的采样器功能并跟踪创建的实例数。

Try to cache IO-Operations with MapDB . 尝试使用MapDB缓存IO操作。

You can do like this to cache it to an disk-based file database: 您可以这样将其缓存到基于磁盘的文件数据库中:

import java.io.File;
import java.io.IOException;
import java.util.Map;
import org.mapdb.DB;
import org.mapdb.DBMaker;

/**
 * Singleton class.
 */
public class DBManager 
{
        /**
     * Variables.
     */
    private static File dbFile = new File("path/to/file");
    private DB db;
    private static final String password = "yourPassword";
    private Map<Integer, String> ctDB;
    private static DBManager manager;

   /**
    * Singleton operations.
    */

  /**
   * Static initializer.
   */
  static
  {
     manager = null;
  }

/**
 * Singleton method @see DBManager.getInstance(File dbFile);
 * @return          ->  An object / instance of this class.
 */
public static DBManager getInstance()
{       
    if(isFileDatabaseOK())
    {
        /**
         * Check if an object/instance from this class exists already. 
         */
        if(manager == null)
        {
            manager = new DBManager();
        }

        /**
         * Return an object/instance of this class.
         */
        return manager;
    }
    else
    {
        return null;
    }
}

/**
 * Constructors.
 */

/**
 * Empty default Constructor starts the MapDB instance.
 */
private DBManager() 
{       
    /**
     * Load the database file from the given path
     * and initialize the database.
     */
    initMapDB();
}

/**
 * MapDB initializer.
 */

/**
 * Initialize a MapDB database.
 */
private void initMapDB() 
{
    /**
     * Persistence: Make MapDB able to load the same database from the 
     * file after JVM-Shutdown. Initialize database without @see     org.mapdb.DBMaker.deleteFilesAfterClose()
     * @see <link>https://groups.google.com/forum/#!topic/mapdb/AW8Ax49TLUc</link>
     */
    db = DBMaker.newFileDB(dbFile)
            .closeOnJvmShutdown()       
            .asyncWriteDisable()
            .encryptionEnable(password.getBytes())
            .make();

    /**
     * Create a Map / Get the existing map.
     */
    ctDB = db.getTreeMap("database");
}

/**
 * File existence check.
 * If file doesn't exists -> Create a new db file and inform the user.
 */
private static boolean isFileDatabaseOK() 
{       
    /**
     * If the file doesn't exists (First run) create a new file and 
     * inform the user.
     */
    if(!dbFile.exists())
    {
        try 
        {
            dbFile.getParentFile().mkdirs();
            dbFile.createNewFile();

            /**
             * TODO 
             * System.out.println("Database not found. Creating a new one.");
             */

            return true;
        }
        catch (IOException e)
        {
            /**
             * TODO Error handling
             */
            e.printStackTrace();
            return false;
        }
    }
    else
    {           
        return true;
    }
}

/**
 * Database methods / operations.
 */

/**
 * Get objects by id.
 * @param id    ->  Search parameter.
 * @return      ->  The object that belongs to the id.
 */
public String get(int id) 
{
    return ctDB.get(id);
}

/**
 * Adding objects to the database.
 * @param id -> The key reference to the object as 'id'.
 * @param object -> The object to cache.
 */
public void put(int id, String object)
{
    ctDB.put(id, object);

    db.commit();
}
}

And then do: 然后执行:

 DBManager manager = DBManager.getInstance();
 manager.put(1, "test");
 Sytem.out.println(manger.get(1));

G1GC works well if you set default values for most of the parameters. 如果您为大多数参数设置了默认值,则G1GC可以很好地工作。 Set only key parameters 仅设置关键参数

-XX:MaxGCPauseMillis
-XX:G1HeapRegionSize
-XX:ParallelGCThreads
-XX:ConcGCThreads

and leave everything else to Java. 并将其他所有东西留给Java。

You can find more details at below posts: 您可以在以下帖子中找到更多详细信息:

Java 7 (JDK 7) garbage collection and documentation on G1 G1上的Java 7(JDK 7)垃圾收集和文档

Why do I get OutOfMemory when 20% of the heap is still free? 当20%的堆仍然可用时,为什么会得到OutOfMemory?

Use some memory analyzer tool like mat to know the root cause. 使用诸如mat之类的内存分析器工具了解根本原因。

In your case, it's evident that oldgen is growing. 在您的情况下,很明显oldgen正在增长。 Check for possible memory leaks. 检查是否存在内存泄漏。 If you did not find memory leaks, increase heap memory further. 如果未发现内存泄漏,请进一步增加堆内存。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM