Java 使用BuffereImage加载映像时ram使用率高

Java 使用BuffereImage加载映像时ram使用率高,java,swing,bufferedimage,ram,Java,Swing,Bufferedimage,Ram,我创建了一个程序,可以用FileDialog加载图像,调整其大小,向用户预览图像,然后单击按钮将其保存到文件夹中 我的问题是: 当我运行我的程序时-RAM使用量~50mb 正在加载1mb JPG文件-RAM使用量~93mb 保存1mb JPG文件-RAM使用量~160mb 我希望这个程序是轻量级的,但是在3-4个文件之后,它会占用500mb的RAM空间 我尝试使用System.gc()每次用户保存文件时,它都会将RAM使用量减少约10% 下面是一个加载和保存图像的代码,完整的代码,你可以找到 顺

我创建了一个程序,可以用FileDialog加载图像,调整其大小,向用户预览图像,然后单击按钮将其保存到文件夹中

我的问题是:

  • 当我运行我的程序时-RAM使用量~50mb
  • 正在加载1mb JPG文件-RAM使用量~93mb
  • 保存1mb JPG文件-RAM使用量~160mb
  • 我希望这个程序是轻量级的,但是在3-4个文件之后,它会占用500mb的RAM空间

    我尝试使用
    System.gc()
    每次用户保存文件时,它都会将RAM使用量减少约10%

    下面是一个加载和保存图像的代码,完整的代码,你可以找到

    顺便说一句-为什么加载1mb JPG并保存后大小会增加到10mb

    加载图像的代码:

        FileDialog imageFinder = new FileDialog((Frame)null, "Select file to open:");
                imageFinder.setFile("*.jpg; *.png; *.gif; *.jpeg");
                imageFinder.setMode(FileDialog.LOAD);
                imageFinder.setVisible(true);
                userImagePath = new File(imageFinder.getDirectory()).getAbsolutePath()+"\\"+imageFinder.getFile();
    
                userImagePath = userImagePath.replace("\\", "/");
    
     BufferedImage bimage = new BufferedImage(userImage.getWidth(null), userImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    
                        Graphics2D bGr = bimage.createGraphics();
                        bGr.drawImage(userImage, 0, 0, null);
                        bGr.dispose();
    
                        try {
                            BufferedImage bi = bimage;
                            File outputfile = new File("C:\\Users\\Mariola\\git\\MySQL-viwer\\MySQL viewer\\src\\database_images\\"+userBreedInfo[0]+".jpg");
                            ImageIO.write(bi, "png", outputfile);
                        } catch (IOException e1) {
    
                        }
                }
                System.gc()
    
    保存图像的代码:

        FileDialog imageFinder = new FileDialog((Frame)null, "Select file to open:");
                imageFinder.setFile("*.jpg; *.png; *.gif; *.jpeg");
                imageFinder.setMode(FileDialog.LOAD);
                imageFinder.setVisible(true);
                userImagePath = new File(imageFinder.getDirectory()).getAbsolutePath()+"\\"+imageFinder.getFile();
    
                userImagePath = userImagePath.replace("\\", "/");
    
     BufferedImage bimage = new BufferedImage(userImage.getWidth(null), userImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    
                        Graphics2D bGr = bimage.createGraphics();
                        bGr.drawImage(userImage, 0, 0, null);
                        bGr.dispose();
    
                        try {
                            BufferedImage bi = bimage;
                            File outputfile = new File("C:\\Users\\Mariola\\git\\MySQL-viwer\\MySQL viewer\\src\\database_images\\"+userBreedInfo[0]+".jpg");
                            ImageIO.write(bi, "png", outputfile);
                        } catch (IOException e1) {
    
                        }
                }
                System.gc()
    
    “问题”在于
    ImageIO
    占用了大量内存。然后,这个内存将不会返回到操作系统(这就是为什么即使是对
    System.gc()
    的无需调用也不会返回它),因为JVM就是这样工作的。(承诺内存将返回到操作系统?)正如@Andrew Thompson在评论部分指出的,如果您想要更少的内存消耗,请看一下这个。如果您运行它,您将看到,由于内存限制,它不会消耗太多。这实际上告诉你不要担心。JVM将发挥它的魔力,并根据操作系统所说的空闲内存量来处理内存消耗

    如果它仍然困扰着你,你可以尝试找到任何行为可能不同的
    ImageIO
    替代方案。但在我看来,这不值得你这么做。我的意思是,你只想保存/加载一个图像


    另一个值得一读的问题是

    我不建议使用空的捕捉块。至少要记录异常。您应该记住jpg是一种压缩图像格式。将其解压缩到BuffereImage时,每个像素可能由4个整数值(RGBA)表示,具体取决于您的图像格式/颜色空间。这意味着100x100像素图像占用40000个整数值。
    ImageIO.write
    可能是罪魁祸首。这不一定是泄漏,JVM可能只是不释放资源。您可以忘记
    System.gc()
    ,这仅仅是一个建议,不可靠,并且广泛建议不要使用。@Mär-有没有更好的方法来保存映像并在以后释放资源?“我打算这个程序是轻量级的,但在3-4个文件之后它会占用500mb的RAM空间。”然后用有限的RAM启动JVM!JVM只有在看到需要时才会使用GC。看,谢谢!我会照你说的做。我将我的VM参数设置为-Xmx200m,正如预期的那样,程序在260mb下运行。我将尝试找到比
    ImageIO
    更好的解决方案。我只是希望有某种方法来限制程序中的RAM,而不是JVM的起始参数:)与其说
    ImageIO
    使用了很多内存,不如说将解码后的像素保留在内存中(就像
    BufferedImage
    那样)需要一定数量的内存(宽度*高度*字节/像素)。