我遇到了垃圾回收错误:java.lang.OutOfMemoryError:超出了我要解决的GC开销限制。
在日志中,生成PDF报告时我看到一个潜在的问题。 这段代码可能已经超过2年了。问题开始于两天前。
这段代码会导致内存泄漏吗?我更担心作者接受一个输出流并且它没有被关闭。 Doc正在关闭,是否足够?这段代码已经运行了好几年了。
在下面的代码编写器中被刷新但未关闭。这是潜在的内存泄漏吗?
public void formatAndStream(OutputStream out) throws Exception {
// Translate order to something more manageable.
// Only the reports know which fields have meaning to them, so delegate this.
List<FormField> ffs = buildFieldOrder();
/**
* Note on HeaderFooter and iText's built-in setHeader() setFooter() **
* These can only contain text and so do not meet all our needs.
* We must instead manually build a header and upper footer.
*/
doc = new Document(pageSize);
doc.addAuthor(I18.N("repfmt.pdfAuthor"));
doc.addTitle(pdfTitle);
doc.addCreationDate();
doc.addProducer();
// Build our PDF writer Listeners.
// DocListener is too generic.
PdfPageEventHelper list = new PdfPageEventHelper() {
public void onStartPage(PdfWriter writer, Document document) {
doStartPage(writer, document);
}
public void onEndPage(PdfWriter writer, Document document) {
try {
prepareForNextPage(document);
} catch (Exception e) {
System.err.println("Error preparing for page " + pageNumber);
e.printStackTrace();
}
}
};
// Configure our PDF output.
writer = PdfWriter.getInstance(doc, out);
createDate = new Date();
writer.setPageEvent(list);
/*
Margins
Margins when set apply to the NEXT page to be written.
Ergo, you must set margins for page 1 with prescient knowledge of the first section to be rendered.
Each margin set thereafter should occur on end page.
Subsect header renders must occur on begin page.
*/
currentReport = findNextCareSubsection(ffs, true);
currentSubsection = createSubsection(currentReport);
prepareForNextPage(doc);
// open the doc for writing
doc.open();
try {
// Write the first section (it's special)
if (currentSubsection != null) {
currentSubsection.write(doc, docWidth, writer);
}
boolean pageBreakNeeded = false;
// Iterate the elements in order, rendering them to the PDF output.
for (FormField ff : ffs) {
currentReport = null;
currentSubsection = null;
if (ff instanceof GeneralField) {
GeneralField gf = (GeneralField)ff;
switch (gf) {
case Pagebreak:
pageBreakNeeded = true;
break;
default:
System.err.println("Dropping unsupported GeneralField: " + gf);
}
} else {
SubsectionRenderer sr = this.createSubsection(ff);
if (sr != null) {
currentReport = ff;
currentSubsection = sr;
// If we can fit the subsection's first header on this page, add() it.
// If we cannot, break the page.
// subsequent header paints must happen as part of a margin set/fill operation
float height = currentSubsection.getNextPageHeaderHeight(docWidth);
if (!pageBreakNeeded && Util.hasAtLeast(doc, writer, height)) {
currentSubsection.writeHeader(doc, docWidth); // first hit is here
} else {
doc.newPage();
pageBreakNeeded = false;
}
if (pageBreakNeeded) { // second hit here
doc.newPage();
pageBreakNeeded = false;
}
currentSubsection.write(doc, docWidth, writer);
}
}
}
} catch (Exception t) {
doc.add(new Paragraph(I18.N("repfmt.errorMsg"), Defaults.FONT_ERROR));
throw t;
} finally {
try {
writer.flush();
doc.close();
} catch (Throwable t) {
// prevent stream close exceptions from masking real exceptions
System.err.println(I18.N("repfmt.4") + t);
}
}
}