【问题标题】:Javafx .exe crashes while invoking javafx.scene.effect.DropShadowJavafx .exe 在调用 javafx.scene.effect.DropShadow 时崩溃
【发布时间】:2021-02-02 12:40:33
【问题描述】:

调用javafx.scene.effect.DropShadow 时,我的本机 javafx 应用程序在运行时崩溃。 该应用程序仅在我注释掉相关代码时才有效。如何使用 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);
    }
}

【问题讨论】:

标签: java javafx gluon graalvm graalvm-native-image


【解决方案1】:

TL;DR

反射列表中缺少类com.sun.scenario.effect.impl.prism.PrMergePeer。添加它,再次构建原生镜像,它就会工作。

说明

如果您的应用程序在 JVM/Hotspot 上运行良好(即通过mvn javafx:run),但在运行时通过本机映像失败(即通过mvn client:run),通常这是一个配置问题,这可能很容易解决。

通常,它与反射列表中缺少的类有关,这会导致类未找到异常。

但是,有时,无法以反射方式调用的缺失类不会引发异常,并且应用程序会继续运行,但会出现一些意外行为。 DropShadow 效果似乎就是这种情况。

这使得事情更难追踪。 class not found 异常已经给出了缺少哪个类的提示,但在当前情况下,运行时异常本身没有。

正如这里所解释的,https://docs.gluonhq.com/#_jni_and_reflection,客户端插件在target/client/$arch-$os/gvm/reflectionconfig-$arch-$os.json 下创建一个反射配置文件,其中包含一组反射使用的 JavaFX 类。

但是,这一套并不完整,有时还缺少一些类。一旦确定了这些,就有两种选择:

  • 将它们添加到 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,并添加类(以及所需的字段/方法):
{
  "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"] }]
}

后者是首选选项,因为它只包括给定类所需的方法和字段,而前者包括所有方法和字段。

无论如何,我们仍然需要发现缺失的类。我们可以从堆栈跟踪中检查涉及的 JavaFX 类,或者我们可以使用 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,并探索所有可能的场景(以便代理可以在运行时发现使用的类和资源)。

  • 探索添加到src/main/resources/META-INF/native-image 的文件。

在 DropShadow 效果失败的情况下,客户端插件生成的配置文件中唯一缺少的相关类是 com.sun.scenario.effect.impl.prism.PrMergePeer

  • 最后,再次运行mvn client:build client:run,创建并运行原生镜像。

如果您保留src/main/resources/META-INF/native-image,则其中的配置文件将与客户端插件已创建的配置文件结合使用。或者,您可以删除它们,只需使用上述两个选项之一:将类添加到 reflectionList 或创建一个 json 文件。

【讨论】:

    猜你喜欢
    • 2021-02-19
    • 2010-10-18
    • 1970-01-01
    • 2017-04-27
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多