这是因为内存泄漏吗?
Is This Because of Memory Leakeage?
我经常从本地服务器获取图像,我想在 JPanel 上显示它们。
我编写的代码可以正常运行一段时间。但是一段时间后(大约 5 分钟),我收到此错误:
Exception in thread "Thread-0" java.lang.InternalError: a fault occurred in an unsafe memory access operation
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageR$
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.ja$
at SICK.DisplayImage.updatePane(DisplayImage.java:225)
at SICK.DisplayImage.access[=10=]0(DisplayImage.java:35)
at SICK.DisplayImage.run(DisplayImage.java:356)
at java.lang.Thread.run(Thread.java:748)
这是我从服务器读取图像的地方:
private BufferedImage updatePane(JLabel label) {
try {
InputStream input = new URL("http://192.168.250.21:8080/NewImage.jpg").openStream();
ImageInputStream stream = ImageIO.createImageInputStream(input);
ImageReader reader = ImageIO.getImageReaders(stream).next();
reader.setInput(stream);
int width = reader.getWidth(0);
int height = reader.getHeight(0);
ImageTypeSpecifier spec = reader.getImageTypes(0).next();
BufferedImage image = MappedImageFactory.createCompatibleMappedImage(width, height, spec);
ImageReadParam param = reader.getDefaultReadParam();
param.setDestination(image);
image = reader.read(0, param);
stream.close();
input.close();
initialize(image, label);
return image;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
这是我将图像和 JLabel 添加到 JPanel 的初始化函数:
private void initialize(BufferedImage image, JLabel label) {
GridBagConstraints c = new GridBagConstraints(0,0,1,1,0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NORTHWEST,
new Insets(0, 0, 0, 0), 0, 0);
JLabel imgLabel = new JLabel(new ImageIcon(image));
int placeInY = 0;
c.fill = GridBagConstraints.BOTH;
c.weightx = 0;
c.weighty = 0;
c.gridx = 0;
c.gridy = placeInY++;
c.gridheight = 1;
c.gridwidth = 8;
pane.add(imgLabel, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 0;
c.weighty = 0;
c.gridx = 2;
c.gridy = placeInY++;
c.gridheight = 1;
c.gridwidth = 1;
pane.add(label, c);
this.add(pane);
}
这是我的主要功能:
public static void main(String[] args) {
final DisplayImage page = new DisplayImage();
final Thread t1 = new Thread(new Runnable() {
public void run() {
while(true) {
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
page.removeAll();
page.updatePane(new JLabel("New Image"));
page.validate();
page.repaint();
}
}
});
SwingUtilities.invokeLater(new Runnable() {
public void run() {
t1.start();
}
});
}
错误发生在image = reader.read(0, param);
行
我查看了这个错误信息,据说这个错误的发生有几个原因。
其中之一是图片来源可能无效,但我检查过,服务器一直在提供图片。
其中之一是RAM可能内存不足(内存泄漏)。我不确定,但这看起来更像。
如果这个错误是内存泄漏引起的,我该如何解决?
注意:我将此代码用于流式传输图像:https://github.com/haraldk/TwelveMonkeys/blob/master/sandbox/sandbox-common/src/main/java/com/twelvemonkeys/image/MappedImageFactory.java
编辑:我的 linux 系统有 512 MB 的 RAM。我试图在我有 16 GB RAM 的 PC 上得到这个错误,但即使我已经等待了 45 分钟,错误也没有发生。
我用 VisualVM 监控了 JVM 45 分钟。这是堆和元空间:
堆没有增加,但元空间不断增加。我还在看,它还在增加。但是元空间大小也会自动增加。
正如我所读 here,如果需要,元空间大小会自动增加。但在我看来;如果没有剩余未使用的 RAM 来增加大小,则可能导致内存泄漏错误。正如我上面提到的,我在我的 Linux 系统上遇到了这个错误,该系统有 512 MB 的 RAM。
我想,我必须等待很长时间才能在我的 16 GB RAM PC 上发生此错误。
你认为我对内存泄漏的看法是正确的吗?如果是,我该如何解决?
编辑 2:我检查了 Linux 系统中 JVM 的内存使用情况。以下是他们得到错误后的结果:
>sudo jcmd 1955 GC.heap_info
Java HotSpot(TM) Client VM warning: Insufficient space for shared memory file:
2616
Try using the -Djava.io.tmpdir= option to select an alternate temp location.
1955:
def new generation total 2560K, used 747K [0xac200000, 0xac4c0000, 0xaec00000)
eden space 2304K, 32% used [0xac200000, 0xac2baf78, 0xac440000)
from space 256K, 0% used [0xac440000, 0xac440000, 0xac480000)
to space 256K, 0% used [0xac480000, 0xac480000, 0xac4c0000)
tenured generation total 5504K, used 5210K [0xaec00000, 0xaf160000, 0xb4000000)
the space 5504K, 94% used [0xaec00000, 0xaf1169d8, 0xaf116a00, 0xaf160000)
Metaspace used 7798K, capacity 7957K, committed 8088K, reserved 8496K
我无法将我的元空间大小降低到 10 MB 以下,因为它立即给出了下面的内存不足错误。因此,我使用以下命令将 PC 上的 Metaspace 降低到 13 MB,堆大小降低到 40MB:
java -jar -XX:MaxMetaspaceSize=13m -Xmx40m --illegal-access=warn gui.for.linux-0.0.1-SNAPSHOT.jar
但是当元空间已满时,我得到这个错误:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "StreamCloser"
所以我无法通过降低 PC 上的堆和元空间大小来重现我在 Linux 系统上遇到的错误。
但是Linux系统中JVM元空间使用94%后报错
我无法弄清楚导致错误发生的原因。
Vyacheslav 在 中的回答解释了元空间增加的原因。
我运行带有-Djava.compiler=NONE
选项的应用程序,元空间没有增加。
我经常从本地服务器获取图像,我想在 JPanel 上显示它们。
我编写的代码可以正常运行一段时间。但是一段时间后(大约 5 分钟),我收到此错误:
Exception in thread "Thread-0" java.lang.InternalError: a fault occurred in an unsafe memory access operation
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method)
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageR$
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.ja$
at SICK.DisplayImage.updatePane(DisplayImage.java:225)
at SICK.DisplayImage.access[=10=]0(DisplayImage.java:35)
at SICK.DisplayImage.run(DisplayImage.java:356)
at java.lang.Thread.run(Thread.java:748)
这是我从服务器读取图像的地方:
private BufferedImage updatePane(JLabel label) {
try {
InputStream input = new URL("http://192.168.250.21:8080/NewImage.jpg").openStream();
ImageInputStream stream = ImageIO.createImageInputStream(input);
ImageReader reader = ImageIO.getImageReaders(stream).next();
reader.setInput(stream);
int width = reader.getWidth(0);
int height = reader.getHeight(0);
ImageTypeSpecifier spec = reader.getImageTypes(0).next();
BufferedImage image = MappedImageFactory.createCompatibleMappedImage(width, height, spec);
ImageReadParam param = reader.getDefaultReadParam();
param.setDestination(image);
image = reader.read(0, param);
stream.close();
input.close();
initialize(image, label);
return image;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
这是我将图像和 JLabel 添加到 JPanel 的初始化函数:
private void initialize(BufferedImage image, JLabel label) {
GridBagConstraints c = new GridBagConstraints(0,0,1,1,0,0, GridBagConstraints.NORTHWEST, GridBagConstraints.NORTHWEST,
new Insets(0, 0, 0, 0), 0, 0);
JLabel imgLabel = new JLabel(new ImageIcon(image));
int placeInY = 0;
c.fill = GridBagConstraints.BOTH;
c.weightx = 0;
c.weighty = 0;
c.gridx = 0;
c.gridy = placeInY++;
c.gridheight = 1;
c.gridwidth = 8;
pane.add(imgLabel, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 0;
c.weighty = 0;
c.gridx = 2;
c.gridy = placeInY++;
c.gridheight = 1;
c.gridwidth = 1;
pane.add(label, c);
this.add(pane);
}
这是我的主要功能:
public static void main(String[] args) {
final DisplayImage page = new DisplayImage();
final Thread t1 = new Thread(new Runnable() {
public void run() {
while(true) {
try {
TimeUnit.MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
page.removeAll();
page.updatePane(new JLabel("New Image"));
page.validate();
page.repaint();
}
}
});
SwingUtilities.invokeLater(new Runnable() {
public void run() {
t1.start();
}
});
}
错误发生在image = reader.read(0, param);
我查看了这个错误信息,据说这个错误的发生有几个原因。
其中之一是图片来源可能无效,但我检查过,服务器一直在提供图片。
其中之一是RAM可能内存不足(内存泄漏)。我不确定,但这看起来更像。
如果这个错误是内存泄漏引起的,我该如何解决?
注意:我将此代码用于流式传输图像:https://github.com/haraldk/TwelveMonkeys/blob/master/sandbox/sandbox-common/src/main/java/com/twelvemonkeys/image/MappedImageFactory.java
编辑:我的 linux 系统有 512 MB 的 RAM。我试图在我有 16 GB RAM 的 PC 上得到这个错误,但即使我已经等待了 45 分钟,错误也没有发生。
我用 VisualVM 监控了 JVM 45 分钟。这是堆和元空间:
堆没有增加,但元空间不断增加。我还在看,它还在增加。但是元空间大小也会自动增加。
正如我所读 here,如果需要,元空间大小会自动增加。但在我看来;如果没有剩余未使用的 RAM 来增加大小,则可能导致内存泄漏错误。正如我上面提到的,我在我的 Linux 系统上遇到了这个错误,该系统有 512 MB 的 RAM。
我想,我必须等待很长时间才能在我的 16 GB RAM PC 上发生此错误。
你认为我对内存泄漏的看法是正确的吗?如果是,我该如何解决?
编辑 2:我检查了 Linux 系统中 JVM 的内存使用情况。以下是他们得到错误后的结果:
>sudo jcmd 1955 GC.heap_info
Java HotSpot(TM) Client VM warning: Insufficient space for shared memory file:
2616
Try using the -Djava.io.tmpdir= option to select an alternate temp location.
1955:
def new generation total 2560K, used 747K [0xac200000, 0xac4c0000, 0xaec00000)
eden space 2304K, 32% used [0xac200000, 0xac2baf78, 0xac440000)
from space 256K, 0% used [0xac440000, 0xac440000, 0xac480000)
to space 256K, 0% used [0xac480000, 0xac480000, 0xac4c0000)
tenured generation total 5504K, used 5210K [0xaec00000, 0xaf160000, 0xb4000000)
the space 5504K, 94% used [0xaec00000, 0xaf1169d8, 0xaf116a00, 0xaf160000)
Metaspace used 7798K, capacity 7957K, committed 8088K, reserved 8496K
我无法将我的元空间大小降低到 10 MB 以下,因为它立即给出了下面的内存不足错误。因此,我使用以下命令将 PC 上的 Metaspace 降低到 13 MB,堆大小降低到 40MB:
java -jar -XX:MaxMetaspaceSize=13m -Xmx40m --illegal-access=warn gui.for.linux-0.0.1-SNAPSHOT.jar
但是当元空间已满时,我得到这个错误:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "StreamCloser"
所以我无法通过降低 PC 上的堆和元空间大小来重现我在 Linux 系统上遇到的错误。
但是Linux系统中JVM元空间使用94%后报错
我无法弄清楚导致错误发生的原因。
Vyacheslav 在
我运行带有-Djava.compiler=NONE
选项的应用程序,元空间没有增加。