Java批量导出SVGD地图为PDF时的内存泄漏问题排查与解决咨询
Java批量导出SVGD地图为PDF时的内存泄漏问题排查与解决咨询
我现在碰到了一个挺头疼的内存泄漏问题,想请教下大家有没有靠谱的解决思路:
我们的程序有个批量导出地图为PDF的功能,就是把1-3页的地图导出到指定文件夹里,功能本身是能跑通的,但有个致命的内存问题:每导出一张地图,Java堆里就会多出一些无法被回收的内存。等导出到25张以上时,程序直接就会抛出内存不足异常崩溃,后续也没法继续导出了。
我用Visual VM的堆分析工具查了下,发现堆里堆积了大量org.apache.batik.dom.GenericText和org.apache.batik.dom.GenericAttr的实例,这些对象一直占着内存没被清理掉。目前我临时做了个 workaround:在程序里检测系统内存,当内存占用过高时就停止导出,等用户重启程序后再继续。这个办法能暂时应付客户,但终究不是长久之计。
想问问大家:有没有办法直接把这些残留的对象从堆里清理掉?或者有没有具体的排查方向,能从根源上避免这个内存泄漏?
我已经过了一遍代码,检查有没有未关闭的转码器或者流,目前看起来是都关了,但也有可能我漏看了。
以下是批量导出PDF的核心代码:
public void printBatchToPDF(final BatchPrint bp, final boolean combine) { final ArrayList<String> usedFileNames = new ArrayList(); final UpdateProgressDialog progress = new UpdateProgressDialog(this, "Creating PDF"); final MainMAPSPanel main = this; Runtime runtime = Runtime.getRuntime(); System.setProperty("org.apache.batik.warn_destination_cache", "false"); // initFileChooser(); jfc.setDialogTitle("Save PDFs To Folder"); UIManager.put("FileChooser.fileNameLabelText", "Folder:"); SwingUtilities.updateComponentTreeUI(jfc); int choice = jfc.showSaveDialog(null); if (choice != JFileChooser.APPROVE_OPTION) { return; } File file = null; final String absPath = jfc.getSelectedFile().getAbsolutePath(); // absPath = jfc.getSelectedFile().getAbsolutePath(); file = new File(absPath); file.mkdir(); SwingWorker worker = new SwingWorker() { @Override protected Object doInBackground() { int index = 0; for (PrintView pv : bp.getViews()) { //////// ArrayList<String> fileNames = new ArrayList(); try { progress.setMainText("Exporting Print Views " + ++index + " OF " + bp.getViews().size()); PageFormat pageFormat = null; PrinterJob printerJob = null; Drawing draw = pv.getDrawing(); // if (draw.getLayers() == null || draw.getLayers().isEmpty()) { draw = DrawingDA.findDrawing(project, draw.getDrawingName(), getConnection()); LayerSet ls = LayerSetDA.find(pv.getLayerset().getSetName(), draw, getConnection()); ArrayList<String> onLayers = new ArrayList(ls.getLayers().size()); ArrayList<String> shadowLayers = new ArrayList(ls.getLayers().size()); for (int i = 0; i < ls.getLayers().size(); i++) { Layer l = ls.getLayers().get(i); boolean on = ls.getVisible().get(i); boolean shadowed = ls.getShadowed().get(i); if (on) { onLayers.add(l.getLayerName()); } if (shadowed) { shadowLayers.add(l.getLayerName()); } } for (Layer l : draw.getLayers()) { if (onLayers.contains(l.getLayerName())) { l.isVisible(true); } if (shadowLayers.contains(l.getLayerName())) { l.isShadowed(true); } } final Drawing drawing = draw; File file = null; String absPath = jfc.getSelectedFile().getAbsolutePath(); file = new File(absPath); //SVGDocument doc = null; LayerSet l = pv.getLayerset(); ArrayList<String> colorCodeNames = ColorCodeDA.getLayerSetColorCodes(l, getConnection()); ArrayList<ColorCode> ccs = new ArrayList(colorCodeNames.size()); if (getActiveDrawingPanel() != null) { Iterator<ColorCode> iter = getActiveDrawingPanel().getColorCodes().iterator(); //ArrayList<ColorCode> ccs2 = getActiveDrawingPanel().getColorCodes(); while(iter.hasNext()) { ColorCode c = iter.next(); if (!c.isRunning()) { iter.remove(); } else if (!colorCodeNames.contains(c.getColorCodeName())) { colorCodeNames.add(c.getColorCodeName()); } } iter = null; } ArrayList<ArrayList<Long>> elementids = new ArrayList(); for (String s : colorCodeNames) { ColorCode c = ColorCodeDA.find(project, s, getConnection()); ColorCodeQueryDA.findAll(c, getConnection()); for (ColorCodeQuery ccq : c.getColorCodeQueries()) { ArrayList<Long> ids = ColorCodeQueryDA.findAffectedElementIDs(new DrawingPanel(pv.getDrawing()), ccq, getConnection()); elementids.add(ids); } ccs.add(c); } //final SVGDocument tempSVGDocument = doc; ArrayList<Rectangle2D> aoiRect = new ArrayList(); for (PrintViewPage pvp : pv.getPages()) { Rectangle2D r = pvp.getRect(); aoiRect.add(r); } if (printerJob == null) { printerJob = PrinterJob.getPrinterJob(); } //if page fomrat is not set then use default page format pageFormat = printerJob.defaultPage(); //ArrayList<String> addedNames = new ArrayList(); //ArrayList<Printable> prints = new ArrayList(); // ArrayList<String> fileNames = new ArrayList(); for (int p = 0; p < pv.getPages().size(); p++) { PrintViewPage pvp = pv.getPages().get(p); String date = ""; String name = ""; String scale = ""; if (pvp.getRect().getWidth() > pvp.getRect().getHeight()) { pageFormat.setOrientation(PageFormat.LANDSCAPE); } else { pageFormat.setOrientation(PageFormat.PORTRAIT); } if (pvp.getSheetName() != null) { name = pvp.getSheetName(); } if (pvp.isToScale()) { scale = " Scale: " + pvp.getScaleString(); } if (pvp.isShowDate()) { SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy"); date = sdf.format(new Date()); } /* double lM = pvp.getLeftMargin(); double rM = pvp.getRightMargin(); double tM = pvp.getTopMargin(); double bM = pvp.getBottomMargin(); */ Paper pagePaper = pageFormat.getPaper(); pagePaper.setSize(pvp.getPageWidthHeight()[0], pvp.getPageWidthHeight()[1]); pageFormat.setPaper(pagePaper); // Transcoder pdfTranscoder = new PDFTranscoder(); Rectangle tempAoiRect; tempAoiRect = new Rectangle((int) aoiRect.get(p).getX(), (int) aoiRect.get(p).getY(), (int) aoiRect.get(p).getWidth(), (int) aoiRect.get(p).getHeight()); double borderWidth = 0; pdfTranscoder.addTranscodingHint(PDFTranscoder.KEY_WIDTH, (float) pvp.getPageWidthHeight()[1] * 96); pdfTranscoder.addTranscodingHint(PDFTranscoder.KEY_HEIGHT, (float) pvp.getPageWidthHeight()[0] * 96); pdfTranscoder.addTranscodingHint(PDFTranscoder.KEY_AOI, tempAoiRect); Rectangle2D.Double rect = new Rectangle2D.Double(tempAoiRect.getX(), tempAoiRect.getY(), tempAoiRect.getWidth(), tempAoiRect.getHeight());
备注:内容来源于stack exchange,提问作者user29701090
相关产品推荐
相关产品推荐

