【发布时间】:2017-05-27 10:40:20
【问题描述】:
我正在对相当大规模(1000 个项目)进行分析,我正在从源代码中提取测试框架的使用情况(例如,检测 assertEquals 以测量断言密度)。为此,我不想考虑任何已被注释掉的陈述。为了做到这一点,我有以下方法:
public static CharSequence replaceAllRegexInFile(CharSequence input, String regex) {
if (regex == null || input == null) {
return input;
}
Pattern pattern = Pattern.compile(regex);
return pattern.matcher(input).replaceAll("");
}
我正在使用以下正则表达式运行此方法来替换 Java cmets:
(\/\*([\S\s]+?)\*\/|(?s)/\*.*?\*/)".
我很清楚 replaceAll 在聚合和返回最终结果的同时分配了大量的中间结果。当然,我可以使用替换,但这不允许我使用正则表达式来替换 cmets。
我明白为什么会抛出堆空间错误,尤其是因为我正在整个机器上同时流式传输所有文件和所有项目。当然,这会占用大量资源,但我无法找到解决我的问题的替代解决方案,因为绝对需要正则表达式替换。
任何建议将不胜感激。
您可以在下面找到堆栈跟踪:
Exception in thread "main" java.lang.OutOfMemoryError
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:598)
at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:735)
at java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:714)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at AnalysisRunner.startAnalysis(AnalysisRunner.java:33)
at AnalysisRunner.main(AnalysisRunner.java:26)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:541)
at java.lang.StringBuffer.append(StringBuffer.java:350)
at java.util.regex.Matcher.appendReplacement(Matcher.java:888)
at java.util.regex.Matcher.replaceAll(Matcher.java:955)
at Business.RegexService.replaceAllRegexInFile(RegexService.java:64)
at Business.FrameWorkDetectionService.extractAllResultsForFile(FrameWorkDetectionService.java:58)
at Business.FrameWorkDetectionService.lambda$extractFrameworkDependencies$0(FrameWorkDetectionService.java:39)
at Business.FrameWorkDetectionService$$Lambda$19/1175339539.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:747)
at java.util.stream.ReduceOps$ReduceTask.doLeaf(ReduceOps.java:721)
at java.util.stream.AbstractTask.compute(AbstractTask.java:316)
at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool.helpComplete(ForkJoinPool.java:1870)
at java.util.concurrent.ForkJoinPool.awaitJoin(ForkJoinPool.java:2045)
at java.util.concurrent.ForkJoinTask.doInvoke(ForkJoinTask.java:404)
at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:734)
at java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:714)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at Business.FrameWorkDetectionService.extractFrameworkDependencies(FrameWorkDetectionService.java:39)
at Business.FrameWorkDetectionService.detectFrameworks(FrameWorkDetectionService.java:26)
at Business.FrameworkService.projectResults(FrameworkService.java:59)
at AnalysisRunner$$Lambda$13/1712669532.apply(Unknown Source)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
是否有替代解决方案不会分配这么多堆空间,但仍允许我同时替换大量文件中的所有 cmets?
非常感谢任何帮助!
【问题讨论】:
-
当您使用低效的正则表达式模式和交替时,Java 中的一个常见问题。使用来自Regex to match a C-style multiline comment 的正则表达式。顺便说一句,在一个模式中重复模式是没有意义的:
/\*([\S\s]+?)\*/匹配与(?s)/\*.*?\*/相同的文本
标签: java regex replace out-of-memory heap-memory