使用 VisualVM 并检查 Tomcat 8.5 catalina.out日志我每次都看到 几乎 (7次出11次左右)当 完整的GC 发生时,日志显示 OutOfMemory (在同一分钟)。< / p>
使用与内存管理有关的Tomcat 参数 : -Xms3G -Xmx = 6G -XX:+ UseG1GC -XX:+ UseStringDeduplication -XX :MaxHeapFreeRatio = 100
起初我认为这是因为默认 -XX:MaxHeapFreeRatio 值 70 ,因为我看到了最大值。在 完整GC - ~10-20%期间,堆大小(当然使用的堆)会显着下降。但是,添加 XX:MaxHeapFreeRatio = 100 并没有解决问题。
虽然这是 内存使用情况 ,但 不同 JVM参数< / em> (无法获得具有旧JVM参数的ATM)在完全GC内存使用 快速增长 后,它在某种程度上相似,同样最大。堆大小和最大堆大小不会下降。
为什么会发生这种情况的任何想法?
更新:我忘了提及之前 完整的GC 和 OutOfMemory 堆大小 甚至不满 时会发生 - 〜5GB。当时我没看到堆达到6GB。
答案 0 :(得分:1)
显然,创建的某些对象无法正确收集垃圾。您可以尝试使用VisualVM的采样器功能并跟踪创建的实例数。
答案 1 :(得分:0)
尝试使用MapDB缓存IO操作。
您可以这样做将其缓存到基于磁盘的文件数据库:
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();
}
}
然后做:
DBManager manager = DBManager.getInstance();
manager.put(1, "test");
Sytem.out.println(manger.get(1));
答案 2 :(得分:0)
如果为大多数参数设置默认值,G1GC运行良好。仅设置关键参数
-XX:MaxGCPauseMillis
-XX:G1HeapRegionSize
-XX:ParallelGCThreads
-XX:ConcGCThreads
将其他所有内容留给Java。
您可以在以下帖子中找到更多详细信息:
Java 7 (JDK 7) garbage collection and documentation on G1
Why do I get OutOfMemory when 20% of the heap is still free?
使用像mat这样的内存分析工具来了解根本原因。
在你的情况下,很明显oldgen正在成长。检查可能的内存泄漏。如果没有发现内存泄漏,请进一步增加堆内存。