Ich habe ein Programm, das lange Zeit unter java-8 lief. Ich wollte jetzt das Programm unter openJDK19 laufen lassen.
Leider bekomme ich eine Exception:
Exception in thread „AWT-EventQueue-0“ java.lang.IllegalAccessError: class core.AttachmentManager (in unnamed module @0x5b03fd8f) cannot access class sun.awt.image.BufferedImageGraphicsConfig (in module java.desktop) because module java.desktop does not export sun.awt.image to unnamed module @0x5b03fd8f
at core.AttachmentManager.createCompatibleImage(AttachmentManager.java:522)
at core.AttachmentManager.addAttachment(AttachmentManager.java:144)
at control.MainControl.addAttachment(MainControl.java:727)
at view.ToolBar$10.actionPerformed(ToolBar.java:169)
…
Wenn ich das richtig verstehe ist das ein Problem mit der Modularisierung von Java. Ich müsste herausfinden in welchem Modul das Package sun.awt.image liegt und dann das entsprechende Modul in module-info.java eintragen, oder?
Hier ist der Code-Abschnitt in dem die Exception auftritt:
Da kommen mehrere Dinge zusammen.
Ja das hängt mit der Modularisierung zusammen. Du müsstest dem Modul java.desktop sagen dass das entsprechende Package für dein Modul geöffnet wird. Da ist das Problem dass dein Modul kein Namen hat, also du hast keine module-info.java.
Dann ist das auch gar nicht so „einfach“ es geht, also man kann beim Kompilieren und Starten sagen, fremde Module bestimmte Sachen öffnen oder exportieren sollen aber das ist denke ich keine schöne Lösung.
Ich sehe eher das Problem, dass du ein sun Package verwendest. Das sollte man nie machen und einen Grund dafür merkst du gerade.
Ich weiß jetzt nicht wofür du diese Klasse brauchst und ob es anders geht.
Dann gäbe es die Möglichkeit beim Kompillieren und beim Ausführen das ganze per --add-exports java.desktop/sun.awt.image=ALL-UNNAMED zu versuchen, aber da kann ich auch nicht garantieren dass es klappt
Ja, müssten VM Arguments sein wenn ich das richtig sehe. Habe ewig nicht mehr Eclipse eingesetzt und noch länger her dass ich ohne Maven/Gradle gearbeitet habe
Mir stellt sich im Moment eher die Frage, warum du die Klasse überhaupt verwendest. Wenn ich das richtig sehe, soll, diese Methode ja in erster Linie „das Bild kopieren“, und da könnte man auch
private static BufferedImage createCompatibleImage(BufferedImage image) {
int w = image.getWidth();
int h = image.getHeight();
BufferedImage result = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = result.createGraphics();
g2.drawRenderedImage(image, null);
g2.dispose();
return result;
}
verwenden. Falls das irgendwo „nicht funktioniert“ oder einen Nachteil hat, wäre ich gespannt, welcher das sein sollte…
Da gibt’s natürlich 1000 Freiheitsgrade. Das, was du bisher gepostet hast, macht ja eine „Kopie“ des Bildes. Wenn es nur darum geht, einen Thumbnail zu erstellen, brauch man ja nicht das komplette Bild nochmal in ein neues, gleichgroßes Bild zu zeichnen. Je nachdem, wie „schön“ der Thumbnail sein soll, gibt es auch verschiedene Möglichkeiten. Aber eine einfache und effiziente Möglichkeit, einen Thumbnail zu erstellen, ist das hier:
package bytewelt;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageThumbnail
{
public static void main(String[] args) throws IOException
{
BufferedImage image = ImageIO.read(new File("./data/image.png"));
BufferedImage thumbnail = createScaledInstance(image, 100);
ImageIO.write(thumbnail, "png", new File("./data/thumbnail.png"));
}
private static BufferedImage createScaledInstance(
BufferedImage image, int w)
{
double scale = (double) w / image.getWidth();
int h = (int) (scale * image.getHeight());
return createScaledInstance(image, w, h);
}
private static BufferedImage createScaledInstance(
BufferedImage image, int w, int h)
{
BufferedImage scaledImage = new BufferedImage(w, h, image.getType());
double scaleX = (double) w / image.getWidth();
double scaleY = (double) h / image.getHeight();
AffineTransform affineTransform =
AffineTransform.getScaleInstance(scaleX, scaleY);
AffineTransformOp affineTransformOp = new AffineTransformOp(
affineTransform, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
return affineTransformOp.filter(image, scaledImage);
}
}
Vielen Dank für deine ausführlichen Infos. Ich bleibe im Moment noch bei meiner Version. Die Bildqualität ist ganz gut und das Erstellen dauert auch nicht so lange.