对于我正在进行的项目,我的任务是创建一种将图像转换为非加密哈希的方法,以便可以轻松地与类似的图像进行比较,但是我遇到了JVM开始的问题。尽管Java Monitoring& amp;管理控制台未报告内存消耗的任何增加。
当我第一次运行应用程序时,任务管理器会报告如下值: 然而,仅仅约30秒后,这些值就会增加一倍或三倍。
我使用JMMC来创建进程的转储,但它只报告了大约1.3MB的使用情况:
对我来说最奇怪的部分是应用程序执行的操作持续约15秒,然后等待100秒(调试),并且在线程休眠的100秒期间,使用的内存会翻倍。
以下是我的两个课程:
ImageHashGenerator.java
package com.arkazex.srcbot;
import java.awt.Color;
import java.awt.Image;
import java.awt.image.BufferedImage;
public class ImageHashGenerator {
public static byte[] generateHash(Image image, int resolution) {
//Resize the image
Image rscaled = image.getScaledInstance(resolution, resolution, Image.SCALE_SMOOTH);
//Convert the scaled image into a buffered image
BufferedImage scaled = convert(rscaled);
//Create the hash array
byte[] hash = new byte[resolution*resolution*3];
//Variables
Color color;
int index = 0;
//Generate the hash
for(int x = 0; x < resolution; x++) {
for(int y = 0; y < resolution; y++) {
//Get the color
color = new Color(scaled.getRGB(x, y));
//Save the colors
hash[index++] = (byte) color.getRed();
hash[index++] = (byte) color.getGreen();
hash[index++] = (byte) color.getBlue();
}
}
//Return the generated hash
return hash;
}
//Convert Image to BufferedImage
private static BufferedImage convert(Image img) {
//Create a new bufferedImage
BufferedImage image = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_3BYTE_BGR);
//Get the graphics
image.getGraphics().drawImage(img, 0, 0, null);
//Return the image
return image;
}
}
Test.java
package com.arkazex.srcbot;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class Test {
public static void main(String[] args) throws IOException {
//Create a hash
byte[] hash = ImageHashGenerator.generateHash(ImageIO.read(new File("img1.JPG")), 8); //Memory grows to around 150MB here
System.out.println(new String(hash));
try{ Thread.sleep(100000); } catch(Exception e) {} //Memory grows to around 300MB here
}
}
编辑:几秒钟后程序停止增长到300MB,没有明显的原因。我没有改变代码中的任何内容,它只是停止了它。
答案 0 :(得分:0)
请参阅/** comments */
public class Test {
public static void main(String[] args) throws IOException {
//Create a hash
/** Here it allocates (3 * resolution^2 )bytes of memory to a byte array */
byte[] hash = ImageHashGenerator.generateHash(ImageIO.read(new File("img1.JPG")), 8); //Memory grows to around 150MB here
/** And here it again allocates the same memory to a String
Why print a String of 150 million chars? */
System.out.println(new String(hash));
try{ Thread.sleep(100000); } catch(Exception e) {} //Memory grows to around 300MB here
}
}
答案 1 :(得分:0)
我认为你在这里缺少的是一些图像类使用堆外内存。这是(推测)JMMC不可见的,因为它只被告知堆上使用情况。操作系统级内存使用情况监视会看到它...因为它正在查看运行应用程序的JVM的总资源消耗。
问题是只有在完成相应的堆上图像对象时才会回收堆外内存块。只有当它们被垃圾收集时才会发生。
几秒钟后程序停止增长到300MB,没有明显的原因。我没有改变代码中的任何内容,它只是停止了它。
我希望JVM决定是时候做一个完整的GC(或类似的东西),这会导致它释放掉堆内存池中的大量空间。这意味着JVM不再需要继续增长池。
(我故意模糊,因为我实际上并不知道现代JVM中的堆外内存分配是如何工作的。但是如果你想调查,可以下载JVM源代码...... )