调用 javafx.scene.effect.DropShadow 时 Javafx .exe 崩溃
Javafx .exe crashes while invoking javafx.scene.effect.DropShadow
我的原生 javafx 应用程序在调用 javafx.scene.effect.DropShadow
时在运行时崩溃。
该应用程序仅在我注释掉相关代码时才有效。如何使用 DropShadow 效果来实现?
错误日志:
[Di. Feb. 02 18:58:50 MEZ 2021][INFO] ==================== RUN TASK ====================
[Di. Feb. 02 18:58:50 MEZ 2021][FINE] PB Command for run until end: c:\Users\...\target\client\x86_64-windows\Cleptomania.exe
[Di. Feb. 02 18:58:50 MEZ 2021][FINE] Start process run until end...
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] java.lang.RuntimeException: Could not create peer Merge for renderer com.sun.scenario.effect.impl.prism.ps.PPSRenderer@7464688f
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.Renderer.getPeerInstance(Renderer.java:254)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.CoreEffect.getPeer(CoreEffect.java:66)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.CoreEffect.getPeer(CoreEffect.java:92)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.CoreEffect.filterImageDatas(CoreEffect.java:106)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.Merge.filterImageDatas(Merge.java:39)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.Merge.filter(Merge.java:172)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.DelegateEffect.filter(DelegateEffect.java:70)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.prism.PrEffectHelper.render(PrEffectHelper.java:166)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.EffectFilter.render(EffectFilter.java:61)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.renderEffect(NGNode.java:2384)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2069)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:479)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:328)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.lang.Thread.run(Thread.java:834)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:519)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] java.lang.IllegalStateException: Operation requires resource lock
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.ManagedResource.assertLocked(ManagedResource.java:96)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.BaseTexture.assertLocked(BaseTexture.java:267)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.ps.BaseShaderContext.setTexture(BaseShaderContext.java:695)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.ps.BaseShaderContext.validateTextureOp(BaseShaderContext.java:591)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.ps.BaseShaderContext.validateTextureOp(BaseShaderContext.java:507)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.BaseGraphics.drawTextureRaw(BaseGraphics.java:727)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.prism.ps.PPSOneSamplerPeer.filterImpl(PPSOneSamplerPeer.java:117)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.prism.ps.PPSEffectPeer.filter(PPSEffectPeer.java:54)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.LinearConvolveCoreEffect.filterImageDatas(LinearConvolveCoreEffect.java:85)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.LinearConvolveCoreEffect.filterImageDatas(LinearConvolveCoreEffect.java:41)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.FilterEffect.filter(FilterEffect.java:195)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.Offset.filter(Offset.java:160)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.Merge.filter(Merge.java:148)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.DelegateEffect.filter(DelegateEffect.java:70)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.prism.PrEffectHelper.render(PrEffectHelper.java:166)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.EffectFilter.render(EffectFilter.java:61)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.renderEffect(NGNode.java:2384)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2069)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:479)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:328)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.lang.Thread.run(Thread.java:834)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:519)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
更新 - 示例代码
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class SampleApp extends Application {
@Override
public void start(Stage stage) throws Exception
{
VBox root = new VBox();
root.getChildren().add(getButtonBox(root));
Scene scene = new Scene(root, 600, 600);
stage.setScene(scene);
stage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
@Override
public void handle(WindowEvent t)
{
Platform.exit();
System.exit(0);
}
});
stage.show();
}
private VBox getButtonBox(Pane pane)
{
VBox box = new VBox();
Button btn = new Button("No Effect");
btn.setOnAction(action -> setChild(pane, false));
Button btnEff = new Button("With Effect");
btnEff.setOnAction(action -> setChild(pane, true));
box.getChildren().addAll(btn, btnEff);
return box;
}
private void setChild(Pane pane, boolean withEffect)
{
VBox box = new VBox();
Text text = new Text("Hello");
text.setFill(Color.WHITE);
text.setFont(Font.font("Courier New", FontWeight.BOLD, 40));
box.getChildren().add(text);
box.setAlignment(Pos.CENTER);
box.setBackground(new Background(new BackgroundFill(Color.BLUE, new CornerRadii(5,5,5,5,false) ,Insets.EMPTY)));
box.setTranslateZ(-4);
if(withEffect)
{
DropShadow dropShadow = new DropShadow();
dropShadow.setRadius(5.0);
dropShadow.setSpread(1.0);
box.setEffect(dropShadow);
}
if(pane.getChildren().size() > 1)
pane.getChildren().set(1, box);
else
pane.getChildren().add(box);
}
public static void main(String args[])
{
launch(args);
}
}
TL;DR
反射列表中缺少 class com.sun.scenario.effect.impl.prism.PrMergePeer
。添加它,重新构建原生镜像,就可以了。
说明
如果您的应用程序 运行 在 JVM/Hotspot 上正常(即通过 mvn javafx:run
),并且在 运行 时间通过本机图像失败(即通过 mvn client:run
),通常是配置问题,可能很容易修复。
通常,它与反射列表中缺少 classes 有关,这会导致 class 未找到异常。
但是,有时,无法反射调用的缺失 class 不会引发异常,并且应用程序保持 运行ning,但会出现一些意外行为。 DropShadow
效果似乎就是这种情况。
这让事情更难追踪。 class not found 异常已经给出了 class 缺失的提示,但在当前情况下,运行time 异常本身并没有。
如这里所述,https://docs.gluonhq.com/#_jni_and_reflection,客户端插件在target/client/$arch-$os/gvm/reflectionconfig-$arch-$os.json
下创建了一个反射配置文件,其中有一组JavaFX classes用于反射.
然而,这一套并不完整,有时会遗漏一些 classes。一旦确定了这些,就有两个选择:
- 将它们添加到 pom 中的
reflectionList
,例如:
<plugin>
<groupId>com.gluonhq</groupId>
<artifactId>client-maven-plugin</artifactId>
<version>0.1.36</version>
<configuration>
<target>${client.target}</target>
<mainClass>${main.class}</mainClass>
<reflectionList>
<list>com.sun.scenario.effect.impl.prism.PrMergePeer</list>
</reflectionList>
</configuration>
</plugin>
- 在
src/main/resources/META-INF/substrate/config
下创建文件 reflectionconfig.json
,并添加 class(以及所需的 fields/methods):
{
"name":"com.sun.scenario.effect.impl.prism.PrMergePeer",
"methods":[{"name":"<init>", "parameterTypes":["com.sun.scenario.effect.FilterContext", "com.sun.scenario.effect.impl.Renderer", "java.lang.String"] }]
}
后者是首选选项,因为它仅包含给定 class 所需的方法和字段,而前者包含所有方法和字段。
无论如何,我们还是要找到失踪的class。我们可以从堆栈跟踪中检查涉及的 JavaFX classes,或者我们可以使用 GraalVM 图像代理,幸运的是,它会为我们做这件事。
GraalVM 图像代理
GraalVM 有一个 Java 代理创建反射配置文件(以及其他),但需要先 运行 在 Hotspot 上安装应用程序。
这可以组合如下:
创建文件夹 src/main/resources/META-INF/native-image
。
将代理添加到 javafx-maven-plugin
:
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.5</version>
<configuration>
<mainClass>${main.class}</mainClass>
<options>
<option>-agentlib:native-image-agent=config-merge-dir=src/main/resources/META-INF/native-image</option>
</options>
</configuration>
</plugin>
运行 mvn javafx:run
,并探索所有可能的场景(因此代理可以在 运行 时间内发现 class 使用的资源和资源) .
浏览添加到 src/main/resources/META-INF/native-image
的文件。
在 DropShadow 效果失败的情况下,客户端插件生成的配置文件中唯一缺少的相关 class 是 com.sun.scenario.effect.impl.prism.PrMergePeer
。
- 最后,运行 再次
mvn client:build client:run
,以创建和 运行 本机图像。
如果您保留 src/main/resources/META-INF/native-image
,其中的配置文件将与客户端插件已经创建的配置文件结合使用。或者,您可以删除它们,只需使用上面解释的两个选项之一:将 class 添加到 reflectionList
或创建一个 json 文件。
我的原生 javafx 应用程序在调用 javafx.scene.effect.DropShadow
时在运行时崩溃。
该应用程序仅在我注释掉相关代码时才有效。如何使用 DropShadow 效果来实现?
错误日志:
[Di. Feb. 02 18:58:50 MEZ 2021][INFO] ==================== RUN TASK ====================
[Di. Feb. 02 18:58:50 MEZ 2021][FINE] PB Command for run until end: c:\Users\...\target\client\x86_64-windows\Cleptomania.exe
[Di. Feb. 02 18:58:50 MEZ 2021][FINE] Start process run until end...
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] java.lang.RuntimeException: Could not create peer Merge for renderer com.sun.scenario.effect.impl.prism.ps.PPSRenderer@7464688f
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.Renderer.getPeerInstance(Renderer.java:254)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.CoreEffect.getPeer(CoreEffect.java:66)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.CoreEffect.getPeer(CoreEffect.java:92)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.CoreEffect.filterImageDatas(CoreEffect.java:106)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.Merge.filterImageDatas(Merge.java:39)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.Merge.filter(Merge.java:172)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.DelegateEffect.filter(DelegateEffect.java:70)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.prism.PrEffectHelper.render(PrEffectHelper.java:166)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.EffectFilter.render(EffectFilter.java:61)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.renderEffect(NGNode.java:2384)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2069)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:479)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:328)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.lang.Thread.run(Thread.java:834)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:519)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] java.lang.IllegalStateException: Operation requires resource lock
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.ManagedResource.assertLocked(ManagedResource.java:96)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.BaseTexture.assertLocked(BaseTexture.java:267)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.ps.BaseShaderContext.setTexture(BaseShaderContext.java:695)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.ps.BaseShaderContext.validateTextureOp(BaseShaderContext.java:591)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.ps.BaseShaderContext.validateTextureOp(BaseShaderContext.java:507)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.prism.impl.BaseGraphics.drawTextureRaw(BaseGraphics.java:727)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.prism.ps.PPSOneSamplerPeer.filterImpl(PPSOneSamplerPeer.java:117)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.prism.ps.PPSEffectPeer.filter(PPSEffectPeer.java:54)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.LinearConvolveCoreEffect.filterImageDatas(LinearConvolveCoreEffect.java:85)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.LinearConvolveCoreEffect.filterImageDatas(LinearConvolveCoreEffect.java:41)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.FilterEffect.filter(FilterEffect.java:195)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.Offset.filter(Offset.java:160)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.Merge.filter(Merge.java:148)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.DelegateEffect.filter(DelegateEffect.java:70)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.scenario.effect.impl.prism.PrEffectHelper.render(PrEffectHelper.java:166)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.EffectFilter.render(EffectFilter.java:61)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.renderEffect(NGNode.java:2384)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2069)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:479)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:328)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at java.lang.Thread.run(Thread.java:834)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:519)
[Di. Feb. 02 18:58:59 MEZ 2021][INFO] [SUB] at com.oracle.svm.core.windows.WindowsJavaThreads.osThreadStartRoutine(WindowsJavaThreads.java:138)
更新 - 示例代码
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
public class SampleApp extends Application {
@Override
public void start(Stage stage) throws Exception
{
VBox root = new VBox();
root.getChildren().add(getButtonBox(root));
Scene scene = new Scene(root, 600, 600);
stage.setScene(scene);
stage.setOnCloseRequest(new EventHandler<WindowEvent>()
{
@Override
public void handle(WindowEvent t)
{
Platform.exit();
System.exit(0);
}
});
stage.show();
}
private VBox getButtonBox(Pane pane)
{
VBox box = new VBox();
Button btn = new Button("No Effect");
btn.setOnAction(action -> setChild(pane, false));
Button btnEff = new Button("With Effect");
btnEff.setOnAction(action -> setChild(pane, true));
box.getChildren().addAll(btn, btnEff);
return box;
}
private void setChild(Pane pane, boolean withEffect)
{
VBox box = new VBox();
Text text = new Text("Hello");
text.setFill(Color.WHITE);
text.setFont(Font.font("Courier New", FontWeight.BOLD, 40));
box.getChildren().add(text);
box.setAlignment(Pos.CENTER);
box.setBackground(new Background(new BackgroundFill(Color.BLUE, new CornerRadii(5,5,5,5,false) ,Insets.EMPTY)));
box.setTranslateZ(-4);
if(withEffect)
{
DropShadow dropShadow = new DropShadow();
dropShadow.setRadius(5.0);
dropShadow.setSpread(1.0);
box.setEffect(dropShadow);
}
if(pane.getChildren().size() > 1)
pane.getChildren().set(1, box);
else
pane.getChildren().add(box);
}
public static void main(String args[])
{
launch(args);
}
}
TL;DR
反射列表中缺少 class com.sun.scenario.effect.impl.prism.PrMergePeer
。添加它,重新构建原生镜像,就可以了。
说明
如果您的应用程序 运行 在 JVM/Hotspot 上正常(即通过 mvn javafx:run
),并且在 运行 时间通过本机图像失败(即通过 mvn client:run
),通常是配置问题,可能很容易修复。
通常,它与反射列表中缺少 classes 有关,这会导致 class 未找到异常。
但是,有时,无法反射调用的缺失 class 不会引发异常,并且应用程序保持 运行ning,但会出现一些意外行为。 DropShadow
效果似乎就是这种情况。
这让事情更难追踪。 class not found 异常已经给出了 class 缺失的提示,但在当前情况下,运行time 异常本身并没有。
如这里所述,https://docs.gluonhq.com/#_jni_and_reflection,客户端插件在target/client/$arch-$os/gvm/reflectionconfig-$arch-$os.json
下创建了一个反射配置文件,其中有一组JavaFX classes用于反射.
然而,这一套并不完整,有时会遗漏一些 classes。一旦确定了这些,就有两个选择:
- 将它们添加到 pom 中的
reflectionList
,例如:
<plugin>
<groupId>com.gluonhq</groupId>
<artifactId>client-maven-plugin</artifactId>
<version>0.1.36</version>
<configuration>
<target>${client.target}</target>
<mainClass>${main.class}</mainClass>
<reflectionList>
<list>com.sun.scenario.effect.impl.prism.PrMergePeer</list>
</reflectionList>
</configuration>
</plugin>
- 在
src/main/resources/META-INF/substrate/config
下创建文件reflectionconfig.json
,并添加 class(以及所需的 fields/methods):
{
"name":"com.sun.scenario.effect.impl.prism.PrMergePeer",
"methods":[{"name":"<init>", "parameterTypes":["com.sun.scenario.effect.FilterContext", "com.sun.scenario.effect.impl.Renderer", "java.lang.String"] }]
}
后者是首选选项,因为它仅包含给定 class 所需的方法和字段,而前者包含所有方法和字段。
无论如何,我们还是要找到失踪的class。我们可以从堆栈跟踪中检查涉及的 JavaFX classes,或者我们可以使用 GraalVM 图像代理,幸运的是,它会为我们做这件事。
GraalVM 图像代理
GraalVM 有一个 Java 代理创建反射配置文件(以及其他),但需要先 运行 在 Hotspot 上安装应用程序。
这可以组合如下:
创建文件夹
src/main/resources/META-INF/native-image
。将代理添加到
javafx-maven-plugin
:
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.5</version>
<configuration>
<mainClass>${main.class}</mainClass>
<options>
<option>-agentlib:native-image-agent=config-merge-dir=src/main/resources/META-INF/native-image</option>
</options>
</configuration>
</plugin>
运行
mvn javafx:run
,并探索所有可能的场景(因此代理可以在 运行 时间内发现 class 使用的资源和资源) .浏览添加到
src/main/resources/META-INF/native-image
的文件。
在 DropShadow 效果失败的情况下,客户端插件生成的配置文件中唯一缺少的相关 class 是 com.sun.scenario.effect.impl.prism.PrMergePeer
。
- 最后,运行 再次
mvn client:build client:run
,以创建和 运行 本机图像。
如果您保留 src/main/resources/META-INF/native-image
,其中的配置文件将与客户端插件已经创建的配置文件结合使用。或者,您可以删除它们,只需使用上面解释的两个选项之一:将 class 添加到 reflectionList
或创建一个 json 文件。