You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 19:07:59