由ReplaceAll正则表达式引起的Java OutOfMemoryError

由ReplaceAll正则表达式引起的Java OutOfMemoryError,java,regex,replace,out-of-memory,heap,Java,Regex,Replace,Out Of Memory,Heap,我正在对一个相当大的规模(1000个项目)进行分析,为此我从源代码中提取测试框架的使用情况(例如,检测assertEquals以测量assert密度)。为此,我不想考虑任何已被注释掉的语句。为了做到这一点,我有以下方法: public static CharSequence replaceAllRegexInFile(CharSequence input, String regex) { if (regex == null || input == null) { retu

我正在对一个相当大的规模(1000个项目)进行分析,为此我从源代码中提取测试框架的使用情况(例如,检测assertEquals以测量assert密度)。为此,我不想考虑任何已被注释掉的语句。为了做到这一点,我有以下方法:

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注释:

(\/\*([\S\s]+?)\*\/|(?s)/\*.*?\*/)". 
我很清楚,replaceAll在聚合和返回最终结果时分配了大量中间结果。当然,我可以使用replace,但这不允许我使用正则表达式来替换注释

我明白为什么会抛出heapspace错误,特别是因为我在整个机器上同时传输所有文件和所有项目。当然,这会占用大量资源,但我无法找到解决问题的替代方案,因为regex的替换显然是一项要求

如有任何建议,将不胜感激

您可以在下面找到stacktrace:

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)
有没有另一种解决方案,它不会分配这么多堆空间,仍然允许我同时替换大量文件中的所有注释


非常感谢您的帮助

可能Java没有为您的应用程序分配足够的内存。您可以尝试使用
-Xmx
-Xms
标志来增加分配的初始和最大内存,例如:

java -Xmx2048m -Xms512m yourApp
调整这些参数,使应用程序不会破碎

通过运行
java-X


如果更改分配的内存没有帮助,请尝试在应用程序运行时使用
jmap-heap:format=b
创建堆转储。然后在某种内存分析器中打开它(例如)。可能代码的其他部分存在内存泄漏。这将检测到它们。

我认为这更像是一条大评论,而不是答案,但是作为答案发布,因为它的格式更丰富

您的正则表达式的性能不好,这可能会导致如此大的内存错误。例如,这是您的正则表达式的图表:

我从中了解到的是,你只是想摆脱块评论。因此,您的正则表达式中存在不同的问题,最重要的是您有不同的模式来执行完全相同的操作,因此您应该只使用其中一种模式,通过这样做,您可以摆脱捕获组和替换,只需使用它们,如:

\/\*[\S\s]+?\*\/".   <--- I removed the capturing group to make it more efficient, since you didn't need it
or 
(?s)/\*.*?\*/".

Java中的一个常见问题是在交替使用低效的正则表达式模式。使用来自的正则表达式。顺便说一句,在一个模式中复制模式是没有意义的:
/\*([\S\S]+?)\*/
(?S)/\*.*?\*/
匹配相同的文本
(?:\/\*[\S\s]+?\*\/|(?s)/\*.*?\*/)".