【发布时间】:2016-01-19 09:01:19
【问题描述】:
我有这个“java.lang.OutOfMemoryError: Java heap space”,我阅读并理解我可以使用 -Xmx1024m 增加我的内存。但我认为在我的代码中我可以改变一些东西,这个错误不再发生。
首先,这是来自 VisualVM 的关于我的记忆的图像:
在图像中你可以看到对象“Pedidos”不是那么大,我有另一个对象“Enderecos”,它的大小越来越少但不完整,因为在对象完成之前我有错误.
重点是:
- 我有 2 个类搜索一个大的 csv 文件(每个类 400.000 个值),我将展示代码。我尝试使用垃圾收集器,将变量设置为空,但无法正常工作,有人可以帮我吗?这是“Pedidos”类的代码,“Enderecos”类是相同的,我的项目只是调用这两个类。
// all Imports
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import Objetos.Pedido;
// CLASS
public class GerenciadorPedido{
// ArrayList I will add all the "Pedidos" Objects
ArrayList<Pedido> listaPedidos = new ArrayList<Pedido>();
// Int that I need to use the values correctly
int helper;
// I create this global because I didnt want to create a new String everytime the for is running (trying to use less memory)
String Campo[];
String Linha;
String newLinha;
public ArrayList<Pedido> getListaPedidos() throws IOException {
// Here I change the "\" and "/" to be accepted be the FILE (the csv address)
String Enderecotemp = System.getProperty("user.dir"), Endereco = "";
char a;
for (int i = 0; i < Enderecotemp.length(); i++) {
a = Enderecotemp.charAt(i);
if (a == '\\') a = '/';
Endereco = Endereco + String.valueOf(a);
}
Endereco = Endereco + "/Pedido.csv";
// Open the CSV File and the reader to read it
File NovoArquivo = new File(Endereco);
Reader FileLer = null;
// Try to read the File
try
{
FileLer = new FileReader(NovoArquivo);
}
catch(FileNotFoundException e) {
JOptionPane.showMessageDialog(null, "Erro, fale com o Vini <Arquivo de Pedido Não Encontrado>");
}
// Read the File
BufferedReader Lendo = new BufferedReader(FileLer);
try
{
// Do for each line of the csv
while (Lendo.ready()) {
// Read the line and replace the caracteres ( needed to funcionality works )
Linha = Lendo.readLine();
newLinha = Linha.replaceAll("\"", "");
newLinha = newLinha.replaceAll(",,", ", , ");
newLinha = newLinha.replaceAll(",,", ", , ");
newLinha = newLinha + " ";
// Create Campo[x] for each value between ","
Campo = newLinha.split(",");
// Object
Pedido pedido = new Pedido();
helper = 0;
// Just to complete the object with the right values if the Campo.length have 15, 16, 17, 18 or 19 of size.
switch (Campo.length) {
case 15: pedido.setAddress1(Campo[9]);
break;
case 16: pedido.setAddress1(Campo[9] + Campo[10]);
helper = 1;
break;
case 17: pedido.setAddress1(Campo[9] + Campo[10] + Campo[11]);
helper = 2;
break;
case 18: pedido.setAddress1(Campo[9] + Campo[10] + Campo[11] + Campo[12]);
helper = 3;
break;
case 19: pedido.setAddress1(Campo[9] + Campo[10] + Campo[11] + Campo[12] + Campo[13]);
helper = 4;
break;
}
// Complete the Object
pedido.setOrder(Campo[0]);
pedido.setOrderValue(Float.parseFloat(Campo[1]));
pedido.setOrderPv(Float.parseFloat(Campo[2]));
pedido.setCombinedOrderFlag(Campo[3]);
pedido.setCombineOrder(Campo[4]);
pedido.setOrderType(Campo[5]);
pedido.setOrderShipped(Campo[6]);
pedido.setOrderCancelled(Campo[7]);
pedido.setTransactionType(Campo[8]);
pedido.setAddress2(Campo[10 + helper]);
pedido.setAddress3(Campo[11 + helper]);
pedido.setPost(Campo[12 + helper]);
pedido.setCity(Campo[13 + helper]);
pedido.setState(Campo[14 + helper]);
// Add the object in the ArrayList
listaPedidos.add(pedido);
// Set everything to null to start again
Campo = null;
Linha = null;
newLinha = null;
}
}
catch(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
// Close the file and run garbage collector to try to clear the trash
Lendo.close();
FileLer.close();
System.gc();
}
// return the ArrayList.
return listaPedidos;
}
}
该项目运行这个类,但是当项目尝试运行另一个(与这个相同,只更改名称和 csv )时,我有内存错误。我不知道如何清除这个 char[] 和你在图像上看到的那么大的字符串。有什么新想法吗?不增加内存真的不行吗?
【问题讨论】:
-
平面文件的大小(以 KB 为单位)是多少?
-
你说的是 400k lines 的 csv 吗?如果你这样做了,并且每行在“pedido”中变成大约 10 个字符串,那么 500 万个字符串实例似乎很合理。
-
@ViniciusMartin 您设置了
Campo = null,但在将该数组中的字符串添加到pedido之前。保留这些引用。 -
@AndréStannek 其中两个字符串变成了浮点数,所以它是 12-13 个字符串,但仍然非常合理。
-
如果您不能/不想花费那么多内存,您应该考虑一下同时需要多少个“pedidos”。也许您可以一个接一个地读取+处理,而不是读取 400k 个对象然后一次性处理所有对象。
标签: java string char out-of-memory heap-memory