Hello everyone,
I am currently porting my application from Java 14 to Java 17 and have encountered a crash that I do not understand. To illustrate this, I used the JFrameRenderer example (https://examples.vtk.org/site/Java/SwingIntegration/JFrameRenderer/) and simply moved the main to another class, JFrameRendererMain.java. So far, so good. But if, in this new class, I add the static method to load the external VTK libraries, the JRE crashes abruptly with the following message:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f9ac8cd14b3, pid=133311, tid=133318
#
# JRE version: OpenJDK Runtime Environment (17.0.16+8) (build 17.0.16+8-Debian-1deb12u1)
# Java VM: OpenJDK 64-Bit Server VM (17.0.16+8-Debian-1deb12u1, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
# Problematic frame:
# V [libjvm.so+0x8d14b3] jni_CallStaticVoidMethod+0xe3
#
# Core dump will be written. Default location: Core dumps may be processed with "/lib/systemd/systemd-coredump %P %u %g %s %t 9223372036854775808 %h %d" (or dumping to [my_path]/Tests/core.133311)
#
# An error report file with more information is saved as:
# [my_path]/Tests/hs_err_pid133311.log
#
# If you would like to submit a bug report, please visit:
# https://bugs.debian.org/openjdk-17
#
However, I thought that if JNI libraries were loaded multiple times, the second and subsequent calls are ignored.
Of course, for the example, this isn’t really a problem, but in my application I have many classes that call VTK and they are not always called in the same order. So I put the loading of JNI libraries in all these classes… And with Java 14, it worked perfectly fine.
I would like to know how to solve this problem. Is this behavior normal with Java 17? Is there a way to ensure that external libraries are only loaded once, but that they are loaded when needed?
Any help would be greatly appreciated.
Below are the two files causing the crash.
JframeRenderer.java:
import java.awt.*;
import javax.swing.*;
import vtk.*;
public class JFrameRenderer extends JFrame {
private static final long serialVersionUID = 1L;
static {
if (!vtkNativeLibrary.LoadAllNativeLibraries()) {
for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {
if (!lib.IsLoaded()) {
System.out.println(lib.GetLibraryName() + " not loaded");
}
}
}
vtkNativeLibrary.DisableOutputWindow(null);
}
private vtkRenderWindowPanel renderWindowPanel;
public JFrameRenderer() {
vtkNamedColors colors = new vtkNamedColors();
double bkg[] = new double[4];
double actorColor[] = new double[4];
colors.GetColor("RoyalBlue", bkg);
colors.GetColor("LemonChiffon", actorColor);
// Create a sphere source
vtkSphereSource sphere = new vtkSphereSource();
sphere.SetRadius(10.0);
// Create a sphere mapper
vtkPolyDataMapper sphereMapper = new vtkPolyDataMapper();
sphereMapper.SetInputConnection(sphere.GetOutputPort());
// create sphere actor
vtkActor sphereActor = new vtkActor();
sphereActor.SetMapper(sphereMapper);
sphereActor.GetProperty().SetColor(actorColor);
// Create a render window panel to display the sphere
renderWindowPanel = new vtkRenderWindowPanel();
renderWindowPanel.setPreferredSize(new Dimension(600, 600));
renderWindowPanel.setInteractorStyle(new vtkInteractorStyleTrackballCamera());
add(renderWindowPanel, BorderLayout.CENTER);
renderWindowPanel.GetRenderer().AddActor(sphereActor);
renderWindowPanel.GetRenderer().SetBackground(bkg);
}
public void render() {
renderWindowPanel.Render();
}
}
JframeRendererMain.java:
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import vtk.vtkNativeLibrary;
public class JFrameRendererMain {
/* Uncommenting the following lines causes the crash */
// static {
// if (!vtkNativeLibrary.LoadAllNativeLibraries()) {
// for (vtkNativeLibrary lib : vtkNativeLibrary.values()) {
// if (!lib.IsLoaded()) {
// System.out.println(lib.GetLibraryName() + " not loaded");
// }
// }
// }
// vtkNativeLibrary.DisableOutputWindow(null);
// }
public static void main(String[] args) {
try {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
JFrame frame = new JFrameRenderer();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
((JFrameRenderer) frame).render();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}