I am constantly getting images from a local server and I want to show them on the JPanel.
I wrote a code that works for a while without any issue. But after some time (approximately 5 min), I get this error:
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$000(DisplayImage.java:35)
at SICK.DisplayImage$1.run(DisplayImage.java:356)
at java.lang.Thread.run(Thread.java:748)
This is where I read images from the server:
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;
}
This is the initialize function where I add the images and the JLabel to the 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);
}
And this is my main function:
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();
}
});
}
The error occurs in the line image = reader.read(0, param);
I checked out this error message and it is said that there are a couple of reasons this error to occur.
One of them is that the source of the images may be invalid but I checked and the server keeps providing the images.
One of them is that the RAM may be out of memory (memory leakage). I don't know for sure but this seems more like it.
If this error is caused by memory leakage, how do I solve it?
Note: I am using this code for streaming images: https://github.com/haraldk/TwelveMonkeys/blob/master/sandbox/sandbox-common/src/main/java/com/twelvemonkeys/image/MappedImageFactory.java
EDIT: I am having this issue in my linux system which has 512 MB of RAM. I tried to get this error on my PC which has 16 GB of RAM but the error didn't occur even though I have waited for 45 minutes.
I have monitored the JVM for 45 minutes with VisualVM. Here is the heap and metaspace:
Heap didn't increase but metaspace kept increasing. I am still watching and it is still increasing. But the metaspace size increases automatically too.
As I have read here, the metaspace size increases automatically, if it is needed. But in my opinion; if there is no unused RAM left to increase the size, it could cause a memory leakage error. As I have mentioned above, I am getting this error on my Linux system which has 512 MB of RAM.
I reckon, I have to wait so freakishly much more for this error to occur on my PC of 16 GB of RAM.
Do you think I am right about the memory leakage? If so, how do I solve it?
EDIT 2: I have checked the memory usage of the JVM in my Linux System. Here are the results of them after getting the error:
>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
I couldn't lower my metaspace size under 10 MB because it instantly gave the out of memory error below. So I lowered my Metaspace to 13 MB and heap size to 40MB on my PC with the command:
java -jar -XX:MaxMetaspaceSize=13m -Xmx40m --illegal-access=warn gui.for.linux-0.0.1-SNAPSHOT.jar
But when metaspace was full, I got this error:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "StreamCloser"
So I couldn't reproduce the error that I am getting on the Linux system by lowering heap and metaspace size on my PC.
But metaspace of JVM in Linux system is 94% used after it gives an error.
I couldn't figure out what is causing the error to occur.