string.split中的Java outOfMemory异常
我有一个很大的txt文件,里面有整数。文件中的每一行都有两个用空格分隔的整数。文件大小为63MBstring.split中的Java outOfMemory异常,java,string,exception,Java,String,Exception,我有一个很大的txt文件,里面有整数。文件中的每一行都有两个用空格分隔的整数。文件大小为63MB Pattern p = Pattern.compile("\\s"); try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { String line; while ((line = reader.readLine()) != null) {
Pattern p = Pattern.compile("\\s");
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
String[] tokens = p.split(line);
String s1 = new String(tokens[0]);
String s2 = new String(tokens[1]);
int startLabel = Integer.valueOf(s1) - 1;
int endLabel = Integer.valueOf(s2) - 1;
Vertex fromV = vertices.get(startLabel);
Vertex toV = vertices.get(endLabel);
Edge edge = new Edge(fromV, toV);
fromV.addEdge(edge);
toV.addEdge(edge);
edges.add(edge);
System.out.println("Edge from " + fromV.getLabel() + " to " + toV.getLabel());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
线程“main”java.lang.OutOfMemoryError中的异常:java堆空间 位于java.util.Arrays.copyOfRange(Arrays.java:2694) 位于java.lang.String。(String.java:203) 位于java.lang.String.substring(String.java:1913) 在java.lang.String.subSequence(String.java:1946) 位于java.util.regex.Pattern.split(Pattern.java:1202) 位于java.util.regex.Pattern.split(Pattern.java:1259) 在SCC.main(SCC.java:25) 为什么我会得到这个例外?如何更改代码以避免它 编辑: 我已经将堆大小增加到2048m。 什么在消费它?这也是我想知道的 据我所知,jvm应该为顶点列表、边集、缓冲读取器的缓冲区和一个小字符串“line”分配内存。我不知道这是从哪里来的
我读过string.split()方法。我认为这会导致内存泄漏,但我不知道该怎么办。最简单的方法:增加堆大小:
向jvm添加-Xmx512m-Xms512m(甚至更多)参数最简单的方法:增加堆大小:
向jvm添加-Xmx512m-Xms512m(甚至更多)参数,使用
-Xmx
jvm选项增加堆内存限制
更多信息。使用
-Xmx
JVM选项增加堆内存限制
更多信息。您有异常,因为您的堆空间已完成。尝试使用
java -Xms512 -Xmx2048 (for example)
您有异常,因为您的堆空间已完成。尝试使用
java -Xms512 -Xmx2048 (for example)
您首先应该尝试的是将文件减小到足以工作的大小。这将允许你评估你的问题有多大 其次,您的问题肯定与
String#split
无关,因为您一次只在一行上使用它。消耗堆的是顶点
和边
实例。您将不得不重新设计它,使其占用更小的空间,或者彻底修改您的算法,以便只处理内存中图形的一部分,其余部分在磁盘上
附言:只是一个一般的Java注释:不要写
String s1 = new String(tokens[0]);
String s2 = new String(tokens[1]);
你只需要
String s1 = tokens[0];
String s2 = tokens[1];
或者甚至直接使用
标记[0]
而不是s1
,因为它同样清晰。您首先应该尝试的是将文件减小到足以工作的大小。这将允许你评估你的问题有多大
其次,您的问题肯定与String#split
无关,因为您一次只在一行上使用它。消耗堆的是顶点
和边
实例。您将不得不重新设计它,使其占用更小的空间,或者彻底修改您的算法,以便只处理内存中图形的一部分,其余部分在磁盘上
附言:只是一个一般的Java注释:不要写
String s1 = new String(tokens[0]);
String s2 = new String(tokens[1]);
你只需要
String s1 = tokens[0];
String s2 = tokens[1];
或者甚至直接使用
标记[0]
而不是s1
,因为它同样清晰。当您在尝试解析内容时获得OOM时,只是您使用的方法不可伸缩。尽管增加堆可能暂时解决这个问题,但它是不可伸缩的。例如,如果明天您的文件大小增加一个数量级或数量级,您将回到原点。
我建议尝试将文件分块读取,缓存文件的x行,读取它,清除缓存,然后重新执行该过程。
您可以使用ehcache或guava cache。当您在尝试解析内容时获得OOM时,只是您使用的方法不可伸缩。尽管增加堆可能暂时解决这个问题,但它是不可伸缩的。例如,如果明天您的文件大小增加一个数量级或数量级,您将回到原点。 我建议尝试将文件分块读取,缓存文件的x行,读取它,清除缓存,然后重新执行该过程。
您可以使用ehcache或guava cache。由于您的程序在java堆中存储了太多数据,因此出现了此异常 尽管Pattern.split()方法中显示了异常,但真正的罪魁祸首可能是代码中的任何大内存用户,例如您正在构建的图形。查看您提供的内容,我怀疑graph数据结构存储了大量冗余数据。您可能需要研究一种更节省空间的图形结构 如果您使用的是Sun JVM,请尝试JVM选项-XX:+HeapDumpOnOutOfMemoryError来创建一个堆转储,并对任何内存过大的用户进行分析,然后使用该分析来优化代码。有关更多信息,请参阅
如果像其他人指出的那样,这对您来说太多了,请尝试增加JVM堆空间,使您的程序不再崩溃。您会遇到此异常,因为您的程序在java堆中存储了太多数据 尽管Pattern.split()方法中显示了异常,但真正的罪魁祸首可能是代码中的任何大内存用户,例如您正在构建的图形。查看您提供的内容,我怀疑graph数据结构存储了大量冗余数据。您可能需要研究一种更节省空间的图形结构 如果您使用的是Sun JVM,请尝试JVM选项-XX:+HeapDumpOnOutOfMemoryError来创建一个堆转储,并对任何内存过大的用户进行分析,然后使用该分析来优化代码。有关更多信息,请参阅
如果像其他人指出的那样,这对您来说太多了,请尝试增加JVM堆空间,使您的程序不再崩溃。您解析字符串的方式可能会改变
try (Scanner scanner = new Scanner(new FileReader(filePath))) {
while (scanner.hasNextInt()) {
int startLabel = scanner.nextInt();
int endLabel = scanner.nextInt();
scanner.nextLine(); // discard the rest of the line.
// use start and end.
}
我怀疑内存消耗实际上是在您构建的数据结构中,而不是在您读取数据的方式中,但这应该会使它更加明显。您解析字符串的方式可能会改变
try (Scanner scanner = new Scanner(new FileReader(filePath))) {
while (scanner.hasNextInt()) {
int startLabel = scanner.nextInt();
int endLabel = scanner.nextInt();
scanner.nextLine(); // discard the rest of the line.
// use start and end.
}
我怀疑