Garbage collection 在java中使用ANTLR
我正试图用ANTLR解析一个大日志(30字节)文件。Garbage collection 在java中使用ANTLR,garbage-collection,out-of-memory,antlr,Garbage Collection,Out Of Memory,Antlr,我正试图用ANTLR解析一个大日志(30字节)文件。 但它在OOM中崩溃,或者在解析器工作时变得非常缓慢 正如我所知, 1.Lexer扫描文本和yeid标记 2.解析器使用给定规则的令牌 已经使用的令牌应该由gc收集,但似乎不是。 你能告诉我有什么问题吗? (语法或代码) 下面是最小化的语法和代码 LogParser.g grammar LogParser; options { language = Java; } rule returns [Line result] : st
但它在OOM中崩溃,或者在解析器工作时变得非常缓慢 正如我所知,
1.Lexer扫描文本和yeid标记
2.解析器使用给定规则的令牌 已经使用的令牌应该由gc收集,但似乎不是。
你能告诉我有什么问题吗? (语法或代码) 下面是最小化的语法和代码 LogParser.g
grammar LogParser;
options {
language = Java;
}
rule returns [Line result]
:
stamp WS text NL
{
result = new Line();
result.setStamp(Integer.parseInt($stamp.text));
result.setText($text.text + $NL.text);
}
;
stamp
:
DIGIT+
;
text
:
CHAR+
;
DIGIT
:
'0'..'9'
;
CHAR
:
'A'..'Z'
;
WS
:
' '
;
NL
:
'\r'? '\n'
;
Test.java
import java.io.IOException;
import org.antlr.runtime.ANTLRFileStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
public class Test {
public static void main(String[] args) {
try {
CharStream input = new ANTLRFileStream("aaa.txt");
LogParserLexer lexer = new LogParserLexer(input);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
LogParserParser parser = new LogParserParser(tokenStream);
int count = 0;
while (true) {
count++;
parser.rule();
parser.setBacktrackingLevel(0);
if (0 == count % 1000)
System.out.println(count);
}
} catch (IOException e) {
e.printStackTrace();
} catch (RecognitionException e) {
e.printStackTrace();
}
}
}
Line.java
public class Line {
private Integer stamp;
private String text;
public Integer getStamp() {
return stamp;
}
public void setStamp(Integer stamp) {
this.stamp = stamp;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
@Override
public String toString() {
return String.format("%010d %s", stamp, text);
}
}
aaa.txt,随机生成的内容。它的大小约为30兆字节
0925489881 BIWRSAZLQTOGJUAVTRWV
0182726517 WWVNRKGGXPKPYBDIVUII
1188747525 NZONXSYIWHMMOLTVPKVC
1605284429 RRLYHBBQKLFDLTRHWCTK
1842597100 UFQNIADNPHQYTEEJDKQN
0338698771 PLFZMKAGLGWTHZXNNZEU
1971850686 TDGYOCGOMNZUFNGOXLPM
1686341878 NTYUXJSVQYXTBZAFLJJD
0849759139 YRXZSVWSZDBJPSNSWNJH
:
:
:
样品发生器
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;
public class EntryPoint {
/**
* @param args
*/
public static void main(String[] args) {
FileWriter fw = null;
try {
int size = 20;
String formatLength = Integer.toString(Integer.MAX_VALUE);
String pattern = "%0" + formatLength.length() + "d ";
Random random = new Random();
File file = new File("aaa.txt");
fw = new FileWriter(file);
while (true) {
int nextInt = random.nextInt(Integer.MAX_VALUE);
StringBuilder sb = new StringBuilder();
sb.append(String.format(pattern, nextInt));
for (int i = 0; i < size; i++) {
sb.append((char) ('A' + random.nextInt(26)));
}
fw.append(sb);
fw.append(System.getProperty("line.separator"));
if (file.length() > 30000000)
break;
}
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
我相信无缓冲的气流是你想要的。可能还需要取消缓冲字符流。您给了它多少内存?试试-Xmx256M之类的。默认情况下,它使用CommonTokenStream将所有令牌保留在内存中。如何防止CommonTokenStrem将所有令牌保留在内存中?我想让GC收集解析器已经使用的令牌。必须实现我自己的令牌流接口吗?谢谢你的回答。关键点是CommonTokenStream将所有令牌保留在内存中。将CommonTokenStream替换为UnbufferedTokenStream并更改语法,它就可以按照我的意愿工作了。
85000
86000
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at org.antlr.runtime.Lexer.emit(Lexer.java:160)
at org.antlr.runtime.Lexer.nextToken(Lexer.java:91)
at org.antlr.runtime.BufferedTokenStream.fetch(BufferedTokenStream.java:133)
at org.antlr.runtime.BufferedTokenStream.sync(BufferedTokenStream.java:127)
at org.antlr.runtime.CommonTokenStream.consume(CommonTokenStream.java:67)
at org.antlr.runtime.BaseRecognizer.match(BaseRecognizer.java:106)
at LogParserParser.text(LogParserParser.java:190)
at LogParserParser.rule(LogParserParser.java:65)
at Test.main(Test.java:21)