JavaFX 程序的介绍和安全防范

JavaFX 介绍

JavaFX 是一个开源的下一代客户端应用平台,适用于基于 Java 构建的桌面、移动端和嵌入式系统。 它以 Java 为基础构建,旨在创建具有现代、硬件加速用户界面的高性能、可携带的富客户端应用。

JavaFX 基础知识

核心特性

1. 现代用户界面

采用先进的图形渲染引擎和丰富的 UI 控件,可创建具有现代感的用户界面。这些 UI 控件包括各种布局容器、按钮、文本框、列表视图等,支持 CSS 样式和自定义皮肤,能够满足不同应用的界面需求。

2. 硬件加速

充分利用现代图形硬件的加速能力,提高图形和动画的渲染性能,使应用能够提供更流畅的视觉效果和更复杂的交互体验。

3. 支持跨平台

基于 Java 的跨平台特性,JavaFX 应用可以在多个操作系统上运行,如 Windows、macOS、Linux  等,确保应用的一致性和可移植性,可以从官网上下载对应版本和系统的 sdk,官网网址:https://gluonhq.com/products/javafx/

4. CSS 样式支持

通过 CSS 定制控件外观,实现主题切换和现代化设计。

5. 模块化设计

JavaFX 采用模块化架构,将功能划分为多个模块,如 javafx.scene、javafx.controls、javafx.fxml 等。开发者可以根据应用需求选择所需的模块,减少不必要的依赖。

6. 丰富的媒体支持

集成了对音频、视频、图像等多媒体内容的播放和支持,支持 Web 内容嵌入和视频/音频播放(MediaPlayer、MediaView),也支持对 H.265/HEVC 等视频编码格式,可实现各种媒体功能。

7. 响应式设计

内置布局管理器(VBox、BorderPane 等)用于适配不同分辨率,绑定 API 实现数据可以实现和 UI 的自动同步(如 Property 与 Binding)等功能。

8. 社区支持

JavaFX 拥有一个活跃的开发者社区,社区成员积极参与开发和维护,提供各种工具和框架来扩展 JavaFX 的功能。

常见应用场景

桌面应用开发:JavaFX 的跨平台特性和丰富的 UI 控件使其成为开发桌面应用的理想选择,如办公软件、图像处理工具、媒体播放器等。

企业应用:可用于构建企业级的富客户端应用,如金融分析软件、企业资源管理(ERP)系统、客户关系管理(CRM)系统等,提供高效的数据展示和交互功能。

嵌入式系统:凭借其高效的性能和可定制性,适用于嵌入式设备,如智能电视、工业控制系统、医疗设备等,为这些设备提供图形用户界面。

媒体播放器:JavaFX 支持音频、视频、图像等多媒体内容,适用于教育、科学等方面,可以提高页面展示。

JavaFX 基础模块介绍

JavaFX 的基础模块涵盖了从窗口管理、场景图、布局、控件、事件处理、属性绑定到样式和动画等多个方面。它提供了现代化的 API 和丰富的功能,使得开发复杂的桌面应用变得简单高效。

提示:从 JDK 11 开始,JavaFX 作为独立模块分发(需单独从官网上下载 sdk)

应用程序生命周期

Application 作为核心类,是所有 JavaFX 应用的入口类,管理 JavaFX 应用的生命周期 init()、start()、stop(),示例如下:

import javafx.application.Application;
public class Main extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        //ui代码
    }
    public static void main(String[] args) {
        launch(args);
    }
}

窗口与场景

Stage 管理窗口属性(标题、尺寸、全屏等),Scene 是内容容器,存放所有 UI 组件绑定到 Stage,示例如下:

import javafx.scene.Scene;
import javafx.stage.Stage;

Scene scene = new Scene(root, 300, 300); // 场景
primaryStage.setTitle("First App");
primaryStage.setScene(scene);
primaryStage.show();

场景图

javafx.scene.Parent 是所有 JavaFX 场景图(Scene Graph)中的根节点,不能直接实例化,常见子类有 Group、Region、各种布局面板(如 StackPane等),示例如下:

import javafx.scene.Parent;
//引用sample.fxml页面布局
Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("sample.fxml")));

UI控件

常用控件:Button, Label, TextField,CheckBox, RadioButton、ComboBox, ListView, TableView等

import javafx.scene.control.Button;
utton btn = new Button("点我");
btn.setOnAction(e -> System.out.println("Hello JavaFX!"));

布局管理器(Layouts)

  • 核心布局:
  1. HBox/VBox:水平/垂直排列组件
  2. BorderPane:上、下、左、右、中五区域
  3. GridPane:网格布局(类似 HTML 表格)
  4. FlowPane:自动换行布局
  • 示例:
BorderPane root = new BorderPane();
root.setTop(new Label("Header"));
root.setCenter(new Button("Center"));

FXML模块

可以使用可视化拖拽工具(Scene Builder)快速生成 FXML 文件,然后可以通过 FXMLLoader.load() 方法加载 FXML 文件,将 FXML 文件解析为 JavaFX 的节点树(Parent),实现界面与逻辑的分离。

import javafx.fxml.FXMLLoader;
Parent root = FXMLLoader.load(Objects.requireNonNull(getClass().getResource("sample.fxml")));

JavaFX 的简单使用

创建项目

使用 idea 创建一个 javaFX 项目;

导入 sdk

从 JavaFX 官网上下载 JavaFX SDK 并解压,然后在 File -> Project Structure -> Libraries -> + → 选择 JavaFX SDK 的 lib 目录下所有 jar 包,如图所示:

编写启动代码

在项目中的 src/main/java/包名/Main.java 里编写 JavaFX 启动代码,参考所示:

package org.example;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Button btn = new Button("点我!");
        btn.setOnAction(e -> System.out.println("Hello JavaFX!"));
        StackPane root = new StackPane(btn); 
        Scene scene = new Scene(root, 300, 300); // 场景
        primaryStage.setTitle("First App");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

配置 VMOptions

1. 点击 Edit Configurations…,在 Build and Run 里配置 jdk 版本;

2. 在 VM options 中添加如下:

--module-path "F:\SoftTools\javafx-sdk-21.0.7\lib" --add-modules javafx.controls,javafx.fxml,javafx.web 

其中 –module-path 是指 javaFX sdk 的路径,–add-modules 是指依赖的模块,配置如图所示:

运行项目

运行项目能看到 JavaFX 窗口弹出,如图所示:

JavaFX程序安全防范

安全性问题

1. Java 源代码(.java)经过编译后变成字节码(.class),但字节码仍然保留了大量的结构化信息,如类名、方法名、字段名、常量、注释等。

2. 字节码是为 JVM 设计的”中间代码”,不是机器码,可读性较高;

3. 目前市面上有很多成熟的 Java 反编译工具(如 JD-GUI、Jadx 等),反编译工具利用字节码中的结构信息,可以几乎无损地将 .class 文件还原为可读的 Java 源代码。

安全防范

Virbox Protector 工具对 Java 有着成熟的保护方案,包括 Java BCE 和 Java VME 方式两种,其中 Java BCE 方式是对 class 中的所有⽅法的字节码加密,性能好兼容性高,而 Java VME 方式是将JVM字节码转换为自定义的虚拟机指令进行保护,安全性极高。

  • Java BCE 方式是完全支持 JavaFX 程序的保护;
  • Java VME 方式会受到 JavaFX 的调用机制,如果函数全选代码虚拟化后,程序无法运行,所以在使用Java VME 方式时需要注意以下事项。

问题现象

使用 Java VME 方式保护,如果对 jar 包内所有函数全选代码虚拟化后,程序无法运行,会报错如下信息:

Exception in thread “main” java.lang.reflect.InvocationTargetException,
Caused by: java.lang.RuntimeException: Error: class CC000000686383760012EABABDA4A9BE is not a subclass of javafx.application.Application”

JavaFX的调用机制

首先,我们先了解下

javafx.application.Application.launch()  的调用机制。

Application.launch() 是 JavaFX 应用的启动入口,它会初始化 JavaFX 运行环境,并最终调用你自定义的 Application 子类的 start (比如 Stage primaryStage ) 方法。

  1. 当调用 Application.launch()  时,JavaFX 会检查调用它的类(即调用栈中的主类)是否继承javafx.application.Application
  2. 如果主类没有继承自 Application,JavaFX 无法正确启动应用,也无法保证生命周期的完整性,所以程序会报异常。

这也是 JavaFX 区别于普通 Java 程序的一个标志,只有继承了 Application 的类,才能作为 JavaFX 应用的入口。

问题排查

我们先看一下关于 Application.launch() 的 Main 函数虚拟化后和原程序时的反编译效果图:

  • 原程序 Main 函数反编译,如图所示:
  • 这是 Main 虚拟化的结果,如图所示:

就是因为 launch() 被虚拟化了,然后被 Vibox 壳的类加载器给替代了,所以导致找不到应用的启动入口,进而启动时报错。

问题解决方案

对于以上的问题,有两种处理方案,分别如下:

  • 如果使用 Java VME 方式,最好的处理方案就是 main 函数不要进行代码虚拟化,其他函数不受限制。
  • 使用 Java BCE 方式,该方式完全无上述问题限制。

END

滚动至顶部
售前客服
周末值班
电话

电话

13910187371

企业微信
企业微信二维码