У меня есть Java-программа для веб-сервисов, которая читает 13 000 000 дат типа '08 -23-2016 12:54:44 'как строки из базы данных. Моей развивающейся средой являются Java 8, MySQL 5.7 и tomcat 8. Я объявляю строковый массив String [] для его сохранения. Я использую Guice для ввода начальных значений массива данных в пустые. Однако использование памяти по-прежнему огромно. Это мой код:Уменьшение использования памяти в java
String[] data;//size is 1,000,000
void generateDataWrapper(String params) {
//read over 13000000 dates string
ResultSet rs = mySQLCon.readData(params);
clearData(data);//set to empty string
int index = 0;
while(rs.next()) {
data[index++] = rs.getString("date");
if (index == (size - 1)) {//calculate every 1,000,000 total 13 times
//calculate statistics
...
//reset all to empty string
clearData(data);
index = 0;
}
}
}
//mySQLCon. readData function
ResultSet readData(String params) {
try {
String query = generateQuery(params);
Statement postStmt = connection.createStatement();
ResultSet rs = postStmt.executeQuery(query);
return rs;
} catch (Exception e) {
}
return null;
}
Если я называю эту функцию один раз, память достигает 12G, если я называю его снова, память переходит на 20G, на третий раз воля памяти идет в 25G и бросить 'java.lang.OutOfMemoryError: GC предел накладных расходов превысил' ошибка в com.mysql.jdbc.MysqlIO.nextRowFast (MysqlIO.java:2174)
Это часть сообщения об ошибке:
java.lang.OutOfMemoryError: GC overhead limit exceeded
com.mysql.jdbc.MysqlIO.nextRowFast(MysqlIO.java:2174)
com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1964)
com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:3316)
com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:463)
com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3040)
com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2288)
com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2681)
com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2547)
com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2505)
com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1370)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
I изменили алгоритмы сбора мусора на: -XX: + UseConcMarkSweepGC -XX: + CMSIncr ementalMode Но это не помогает. Я попытался изменить данные на статические переменные, все еще будет иметь эту проблему. В настоящее время куча JVM составляет 8 г, память tomcat составляет 24 г, однако я не думаю, что увеличение памяти решит проблему.
Я не понимаю, почему моя память все увеличивается каждый раз, когда я называю эту функцию. Может ли кто-нибудь дать мне какое-нибудь предложение?
Вы пробовали профилирование памяти? или чтение документов API, которые вы используете? в основном, что-нибудь еще, чем дать ему больше памяти? – the8472
Это не полная программа, хотя я могу догадаться, что делают clearData() и размер, это просто догадки. Тем не менее, профилирование памяти, предложенное the8472, может быть вашим лучшим способом: захватить кучу дампа, когда у программы закончится память, и использовать инструмент профилирования, чтобы выяснить, кто держится за память. – Lars
Вам действительно нужно использовать String для хранения даты? Используйте LocalDateTime, и вы можете использовать меньше памяти для каждого объекта. –