在我的代码中有一个级别设置为INFO的log4j记录器,如下所示:
String response = "";
response = someRemoteAPICall();
LOGGER.info("Response: "+response); //line 3因此,在这段代码的第3行,我得到了带有OutOfMemory错误的大型堆转储。
是否可以通过显示日志消息来获取OOM。
我的转储分析显示了下面的Shallow Heap和Retained Heap


这个问题只能通过注释掉日志语句或设置要调试的级别而不是信息或其他一些优雅的方法来解决吗?
我迷路了..。
更新:
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
response = new StringBuffer();
while ((inputLine = in.readLine()) != null) { //OOM
response.append(inputLine);
}
in.close();同样的情况发生在上面的代码中,用于读取大数据。
这是显示此代码相对于浅堆的保留堆的图像:

我的系统属性:
java.runtime.name - Java(TM) SE Runtime Environment
java.runtime.version - 1.8.0_51-b16
java.vm.specification.name - Java Virtual Machine Specification
java.vm.specification.vendor - Oracle Corporation
java.vm.specification.version - 1.8
java.vm.name - Java HotSpot(TM) 64-Bit Server VM
os.arch - amd64
os.name - Linux
os.version - 3.13.0-61-generic
发布于 2015-12-18 11:31:38
哦,是的,可以。
在日志记录行中使用+连接字符串。这意味着,在日志发生之前,将创建一个带有新char数组的新字符串。
而且,如果您的对象的toString()使用了类似的特性,那么您最终可能会得到许多char[]的副本--这并不是太小。
如果你绝对的必须打印出整个事情,你会更好
LOGGER.info("Response: %s", response);只有在实际启用日志信息的情况下才会输出字符串。
如果您知道您的文件很大,并且还想保存它,您可以这样做:
if(LOGGER.isInfoEnabled()) {
File dump = writeToDumpFile(response);
LOGGER.info("Response written to %s", dump.getAbsolutePath());
}(并创建+实现事业上的writeToDumpFile(Response response) )
更新您的更新
你不知道这队伍会有多长。
相反,试着:
InputStreamReaderin = new InputStreamReader(con.getInputStream());
response = new StringBuilder();
char[] buffer = new byte[1024];
int len = in.read(buffer);
while(len > 0 ) {
response.append(buffer, 0, len);
len = in.read(buffer);
}
in.close();使用readLine(),您再次创建了整个字符串的副本:-)
如果你只想转储你的部分回复,你可以在第一次读完之后.
发布于 2015-12-18 11:28:53
也许你不应该放弃你的全部反应。它是否会导致66 of的字符串数据?
哦,即使是一个简单的陈述,比如
Object o = new Object();如果OutOfMemory完全满的话,可能会导致它的出现。
https://stackoverflow.com/questions/34354590
复制相似问题