diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 6afb2e823a9771..cd78818cb54e0c 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -5414,6 +5414,16 @@
quarkus-vertx-web-deployment
${project.version}
+
+ io.quarkus
+ quarkus-awt
+ ${project.version}
+
+
+ io.quarkus
+ quarkus-awt-deployment
+ ${project.version}
+
diff --git a/core/runtime/src/main/java/io/quarkus/runtime/graal/Java2DSubstitutions.java b/core/runtime/src/main/java/io/quarkus/runtime/graal/Java2DSubstitutions.java
deleted file mode 100644
index 0ca2b30ab278e0..00000000000000
--- a/core/runtime/src/main/java/io/quarkus/runtime/graal/Java2DSubstitutions.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package io.quarkus.runtime.graal;
-
-import java.awt.Graphics;
-import java.awt.GraphicsEnvironment;
-
-import com.oracle.svm.core.annotate.AlwaysInline;
-import com.oracle.svm.core.annotate.Substitute;
-import com.oracle.svm.core.annotate.TargetClass;
-
-@TargetClass(GraphicsEnvironment.class)
-final class Target_java_awt_GraphicsEnvironment {
- @AlwaysInline("DCE for things using Java2D")
- @Substitute
- public static Graphics getLocalGraphicsEnvironment() {
- throw new UnsupportedOperationException("Not implemented yet for GraalVM native images");
- }
-}
-
-class Java2DSubstitutions {
-}
diff --git a/extensions/awt/deployment/pom.xml b/extensions/awt/deployment/pom.xml
new file mode 100644
index 00000000000000..a31abf40b9e4a9
--- /dev/null
+++ b/extensions/awt/deployment/pom.xml
@@ -0,0 +1,43 @@
+
+
+ 4.0.0
+
+ io.quarkus
+ quarkus-awt-parent
+ 999-SNAPSHOT
+
+ quarkus-awt-deployment
+ Quarkus - Awt - Deployment
+
+
+ io.quarkus
+ quarkus-arc-deployment
+
+
+ io.quarkus
+ quarkus-awt
+
+
+ io.quarkus
+ quarkus-junit5-internal
+ test
+
+
+
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
diff --git a/extensions/awt/deployment/src/main/java/io/quarkus/awt/deployment/AwtProcessor.java b/extensions/awt/deployment/src/main/java/io/quarkus/awt/deployment/AwtProcessor.java
new file mode 100644
index 00000000000000..f41aadc2a79169
--- /dev/null
+++ b/extensions/awt/deployment/src/main/java/io/quarkus/awt/deployment/AwtProcessor.java
@@ -0,0 +1,75 @@
+package io.quarkus.awt.deployment;
+
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.JniRuntimeAccessBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+
+class AwtProcessor {
+ private static final String FEATURE = "awt";
+
+ @BuildStep
+ ReflectiveClassBuildItem setupReflectionClasses() {
+ return new ReflectiveClassBuildItem(false, false,
+ "sun.awt.X11GraphicsEnvironment",
+ "sun.awt.X11.XToolkit");
+ }
+
+ @BuildStep
+ JniRuntimeAccessBuildItem setupJava2DClasses() {
+ return new JniRuntimeAccessBuildItem(true, true, true,
+ "java.awt.AlphaComposite",
+ "java.awt.Color",
+ "java.awt.geom.AffineTransform",
+ "java.awt.geom.Path2D",
+ "java.awt.geom.Path2D$Float",
+ "java.awt.image.BufferedImage",
+ "java.awt.image.ColorModel",
+ "java.awt.image.IndexColorModel",
+ "java.awt.image.Raster",
+ "java.awt.image.SampleModel",
+ "java.awt.image.SinglePixelPackedSampleModel",
+ "sun.awt.SunHints",
+ "sun.awt.image.BufImgSurfaceData$ICMColorData",
+ "sun.awt.image.ByteComponentRaster",
+ "sun.awt.image.BytePackedRaster",
+ "sun.awt.image.ImageRepresentation",
+ "sun.awt.image.IntegerComponentRaster",
+ "sun.java2d.Disposer",
+ "sun.java2d.InvalidPipeException",
+ "sun.java2d.NullSurfaceData",
+ "sun.java2d.SunGraphics2D",
+ "sun.java2d.SurfaceData",
+ "sun.java2d.loops.Blit",
+ "sun.java2d.loops.BlitBg",
+ "sun.java2d.loops.CompositeType",
+ "sun.java2d.loops.DrawGlyphList",
+ "sun.java2d.loops.DrawGlyphListAA",
+ "sun.java2d.loops.DrawGlyphListLCD",
+ "sun.java2d.loops.DrawLine",
+ "sun.java2d.loops.DrawParallelogram",
+ "sun.java2d.loops.DrawPath",
+ "sun.java2d.loops.DrawPolygons",
+ "sun.java2d.loops.DrawRect",
+ "sun.java2d.loops.FillParallelogram",
+ "sun.java2d.loops.FillPath",
+ "sun.java2d.loops.FillRect",
+ "sun.java2d.loops.FillSpans",
+ "sun.java2d.loops.GraphicsPrimitive",
+ "sun.java2d.loops.GraphicsPrimitiveMgr",
+ "sun.java2d.loops.GraphicsPrimitive[]",
+ "sun.java2d.loops.MaskBlit",
+ "sun.java2d.loops.MaskFill",
+ "sun.java2d.loops.ScaledBlit",
+ "sun.java2d.loops.SurfaceType",
+ "sun.java2d.loops.TransformHelper",
+ "sun.java2d.loops.XORComposite",
+ "sun.java2d.pipe.Region",
+ "sun.java2d.pipe.RegionIterator");
+ }
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(FEATURE);
+ }
+}
diff --git a/extensions/awt/pom.xml b/extensions/awt/pom.xml
new file mode 100644
index 00000000000000..e28ae5059bd3fc
--- /dev/null
+++ b/extensions/awt/pom.xml
@@ -0,0 +1,17 @@
+
+
+ 4.0.0
+
+ io.quarkus
+ quarkus-extensions-parent
+ 999-SNAPSHOT
+
+ quarkus-awt-parent
+ pom
+ Quarkus - Awt - Parent
+
+ deployment
+ runtime
+
+
diff --git a/extensions/awt/runtime/pom.xml b/extensions/awt/runtime/pom.xml
new file mode 100644
index 00000000000000..e4ce9c74395b26
--- /dev/null
+++ b/extensions/awt/runtime/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+ io.quarkus
+ quarkus-awt-parent
+ 999-SNAPSHOT
+
+ quarkus-awt
+ Quarkus - Awt - Runtime
+ Enable AWT and Java2D usage
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ org.graalvm.nativeimage
+ svm
+ provided
+
+
+
+
+
+ io.quarkus
+ quarkus-bootstrap-maven-plugin
+
+
+ maven-compiler-plugin
+
+
+
+ io.quarkus
+ quarkus-extension-processor
+ ${project.version}
+
+
+
+
+
+
+
diff --git a/extensions/awt/runtime/src/main/java/io/quarkus/awt/runtime/graal/AwtFeature.java b/extensions/awt/runtime/src/main/java/io/quarkus/awt/runtime/graal/AwtFeature.java
new file mode 100644
index 00000000000000..bb9dc8b4fdf4df
--- /dev/null
+++ b/extensions/awt/runtime/src/main/java/io/quarkus/awt/runtime/graal/AwtFeature.java
@@ -0,0 +1,22 @@
+package io.quarkus.awt.runtime.graal;
+
+import org.graalvm.nativeimage.ImageSingletons;
+import org.graalvm.nativeimage.hosted.Feature;
+import org.graalvm.nativeimage.impl.RuntimeClassInitializationSupport;
+
+import com.oracle.svm.core.annotate.AutomaticFeature;
+
+@AutomaticFeature
+public class AwtFeature implements Feature {
+ @Override
+ public void afterRegistration(AfterRegistrationAccess access) {
+ final RuntimeClassInitializationSupport runtimeInit = ImageSingletons.lookup(RuntimeClassInitializationSupport.class);
+ final String reason = "Quarkus run time init for AWT";
+ runtimeInit.initializeAtRunTime("com.sun.imageio", reason);
+ runtimeInit.initializeAtRunTime("java.awt", reason);
+ runtimeInit.initializeAtRunTime("javax.imageio", reason);
+ runtimeInit.initializeAtRunTime("sun.awt", reason);
+ runtimeInit.initializeAtRunTime("sun.font", reason);
+ runtimeInit.initializeAtRunTime("sun.java2d", reason);
+ }
+}
diff --git a/extensions/awt/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/awt/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 00000000000000..cebd0192408062
--- /dev/null
+++ b/extensions/awt/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,12 @@
+name: AWT
+metadata:
+ keywords:
+ - awt
+ - font
+ - java2d
+ - image
+ - imageio
+# guide: ...
+ categories:
+ - "miscellaneous"
+ status: "preview"
\ No newline at end of file
diff --git a/extensions/pom.xml b/extensions/pom.xml
index 86697504fe80d9..3ee41c6ef7cbd7 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -201,6 +201,8 @@
vertx-web
+
+ awt
diff --git a/integration-tests/awt/pom.xml b/integration-tests/awt/pom.xml
new file mode 100644
index 00000000000000..2f29b6b7716e47
--- /dev/null
+++ b/integration-tests/awt/pom.xml
@@ -0,0 +1,93 @@
+
+
+ 4.0.0
+
+ io.quarkus
+ quarkus-integration-tests-parent
+ 999-SNAPSHOT
+
+ quarkus-awt-integration-tests
+ Quarkus - Awt - Integration Tests
+
+
+
+ io.quarkus
+ quarkus-awt-deployment
+ ${project.version}
+ pom
+ test
+
+
+ *
+ *
+
+
+
+
+ io.quarkus
+ quarkus-awt
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+
+
+
+ build
+
+
+
+
+
+
+
+
+ native-image
+
+
+ native
+
+
+
+
+
+ maven-surefire-plugin
+
+ ${native.surefire.skip}
+
+
+
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
+
+
+
+
+
+
+
+ native
+
+
+
+
diff --git a/integration-tests/awt/src/test/java/io/quarkus/awt/it/AwtImageResizeIT.java b/integration-tests/awt/src/test/java/io/quarkus/awt/it/AwtImageResizeIT.java
new file mode 100644
index 00000000000000..9c39a3d3809938
--- /dev/null
+++ b/integration-tests/awt/src/test/java/io/quarkus/awt/it/AwtImageResizeIT.java
@@ -0,0 +1,7 @@
+package io.quarkus.awt.it;
+
+import io.quarkus.test.junit.main.QuarkusMainIntegrationTest;
+
+@QuarkusMainIntegrationTest
+public class AwtImageResizeIT extends AwtImageResizeTest {
+}
diff --git a/integration-tests/awt/src/test/java/io/quarkus/awt/it/AwtImageResizeTest.java b/integration-tests/awt/src/test/java/io/quarkus/awt/it/AwtImageResizeTest.java
new file mode 100644
index 00000000000000..70f2f500e4888a
--- /dev/null
+++ b/integration-tests/awt/src/test/java/io/quarkus/awt/it/AwtImageResizeTest.java
@@ -0,0 +1,51 @@
+package io.quarkus.awt.it;
+
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+
+import javax.imageio.ImageIO;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.junit.main.QuarkusMainTest;
+
+@QuarkusMainTest
+public class AwtImageResizeTest {
+
+ @Test
+ public void testImageResize() throws IOException {
+ final String imageData = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZMAAAC5CAYAAADtXNKFAAAQsUlEQVR4Xu3dW6hUZRsH8PfrvsygwAjKLgwis7Ik6KKSIAjTCkUi7CAkQdERIm86XQRCJ6sL6yKz0DA7IwQFlYEmSJkR4YVIRdCRDhfdSNn3PfMxw97j7Nkz+1lz2vN7YbMz13rWrN96nf+8611rzX+OHj36b9EIECBAgEBC4D/CJKFnVQIECBCoCQgTHYEAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2oAAECBAgIE32AAAECBNICwiRNqAABAgQICBN9gAABAgTSAsIkTagAAQIECAgTfYAAAQIE0gLCJE2owKAE/vjjj1L/+fPPP495Gf/++28544wzaj8aAQK9FRAmvfVVPSGwa9eu8s0339QC49tvv639d/0n/l837cQTTyznnXdeqf++9NJLy+mnny5oukG0LIE2AsJE9xiYQATD7t27y+HDh0uMIr744osZh8VMdyLC5bLLLqsFTQRM/GgECHQvIEy6N7PGDAU+/vjj8sknn5T4HT/D2iJYImAiWBYtWmT0MuAD9csvv5STTz65HDp0qBw5cqT8/PPPteOjDZeAMBmu4zHrXk2Exssvv1zefvvt2umqKtqcOXNqb/Axqqi3+p9jG/H/43eMfKLFfx84cGDGm47a8eYVwbJixQrhMmPJ7lZ89tlny5tvvlnidGerdtNNN5WHHnrI8eiOtWdLC5Oe0Y534QiPRx99tHbqqttWn8uoT57X/xwh0Rwi3dSOUInXEz8xBxO/p3qjalf3tNNOKxdeeGFt5CJcujkCnS27c+fO8sgjj5TPPvusoxUiUOJHG6yAMBms/6zbeoxE7r333o5CJEIiTiktXLiwLFmypMSbdPy53y1ec4xiIlgiYLodxdRPi914440Def399url9iJIli9f3vUmtm/fXlatWtX1elaoTkCYVGc51pXiU/8zzzxTnn766bans+KTfPzEaaNhvWS3PoKJcIkRVjfhEvsUn5JjHyeehhvrztHFzh933HHHLH311VeX+fPn10aTYVoP/uYFjVC6gO7BosKkB6jjVjL+ca9du3bKSfWY47j77rvLXXfdNZJvsPVwef7558v+/fvLTz/9VFrd1zLxuMeb3s0331wefPDBkdznfvfhGBFGH2o+LTrViCMm46+//vpJp8LmzZtX+zBjhNLvo/f/7QmTwbjPmq3GP96YG5lqcj0CJD4xzrZP6XFq7J133qmNXOIT81Qt9jv2PyaLZ5tBlZ34zDPPbFwwUa/74YcfTnvV1urVq8uOHTsaLyUukojA1/ovIEz6bz4rtjjdaCT+UW/evHks5hDCYsuWLbVPxVONWGJe5cUXXxwLj247+MqVK2tXbU1se/bsKRdffPG0pfbu3Vuuu+668uOPPzaWfffdd8uyZcumXdcC1QoIk2o9x6LadKOR+CQ+qqe0sgfwpZdeKhs3bpxynuXJJ5+snfLT/i/wwgsvlNtuu20SR1wSfPvtt3dMFH0t1plJGHW8EQtOKyBMpiWyQF1gust94+qsGI24oayUCJV77rmn5UglfOKTuNNe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8ODBli92WO8nGbzs+LwCYTI+x9qeEphWYPny5WXnzp3TLjdxAUHSFdesXViYzNpDa8cIzExg7969tdNeu3btalsgrv6K7weJkYtGQJjoAwQItBSIx41s27at7Nu3b9Lfx0hk2bJlZfHixeQINASEic5AgEBbge+//778/fff5ciRI2XBggW0CLQUECY6BgECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQECb6AAECBAikBYRJmlABAgQIEBAm+gABAgQIpAWESZpQAQIECBAQJvoAAQIECKQFhEmaUAECBAgQ+C9CtmAUEj4ccwAAAABJRU5ErkJggg==";
+ final String expected = "data:image/png;base64,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";
+
+ final byte[] imageBytes = Base64.getDecoder().decode(imageData.split(",", 2)[1]);
+ final String resizeImage = resizeImage(imageBytes, 100);
+ Assertions.assertEquals(expected, resizeImage);
+ }
+
+ private String resizeImage(byte[] imageBytes, int height) throws IOException {
+ BufferedImage inputImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
+
+ int currentW = inputImage.getWidth();
+ int currentH = inputImage.getHeight();
+ int width = currentW * height / currentH;
+ if (currentH < height) {
+ width = currentW;
+ height = currentH;
+ }
+
+ Image originalImage = inputImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
+ BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+ resizedImage.getGraphics().drawImage(originalImage, 0, 0, null);
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ImageIO.write(resizedImage, "png", outputStream);
+
+ return String.format("data:image/png;base64,%s", Base64.getEncoder().encodeToString(outputStream.toByteArray()));
+ }
+
+}
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index b8a59a9881b896..e7649c044d4e25 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -114,6 +114,7 @@
avro-reload
+ awt
bouncycastle
bouncycastle-fips
bouncycastle-fips-jsse