【问题标题】:Creating a runnable .jar with Maven using Java Swing and integrated JavaFX - App crashes when JFXPanel is being instantiated使用 Java Swing 和集成的 JavaFX 使用 Maven 创建可运行的 .jar - 实例化 JFXPanel 时应用程序崩溃
【发布时间】:2021-12-19 14:40:36
【问题描述】:

我想用 Maven 创建可运行的 .jar 文件。 以下代码显示了主类 (App.java)、JFXPanel 实例化的类 (ServiceToolEnty.java) 和 pom.xml 文件。

我创建了一个简单的 JFrame,里面有一个按钮(Java Swing 站点)。单击按钮后,JFXPanel 应打开 JavaFX 线程以运行 javaFX 代码。

当我在 Eclipse IDE 中运行应用程序时,一切正常。 在我使用 Maven 创建 .jar 文件并尝试通过终端 (java -jar test-0.0.1-SNAPSHOT.jar) 运行它后,出现以下错误消息:

Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: javafx/embed/swing/JFXPanel
    at com.carrier.ccr.test.App$1.actionPerformed(App.java:31)
    at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
    at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
    at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
    at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
    at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
    at java.desktop/java.awt.Component.processMouseEvent(Component.java:6626)
    at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3389)
    at java.desktop/java.awt.Component.processEvent(Component.java:6391)
    at java.desktop/java.awt.Container.processEvent(Container.java:2266)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5001)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
    at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
    at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
    at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
    at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4833)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:773)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:716)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:746)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:744)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:743)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
Caused by: java.lang.ClassNotFoundException: javafx.embed.swing.JFXPanel
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    ... 36 more

App.java:


import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Locale;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
public class App extends JFrame{
 
    public App(){
        setSize(500, 180);
        setVisible(true);
        setLayout(null);
        setLocation(100, 100);

        //Button opens the ServiceTool interface
        JButton masterModeServiceTool = new JButton("Click here");
        masterModeServiceTool.setSize(280, 20);
        masterModeServiceTool.setFont(new Font("Arial",Font.PLAIN,15));
        add(masterModeServiceTool);
        masterModeServiceTool.setVisible(true);
        masterModeServiceTool.setLocation(10, 100);
        masterModeServiceTool.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                try {
                    ServiceToolEntry maServ=new ServiceToolEntry();
                    maServ.main();
                    setVisible(false);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

    }


    public static void main(String[] args) {
        App mv =new App();
        mv.addWindowListener(new WindowAdapter()
        {
            public void windowClosing (WindowEvent e) {
                System.exit (0);
            }
        });
    }
}

ServiceToolEnty.java(fx 应用程序的启动位置):


import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class ServiceToolEntry {
    private static void initAndShowGUI() {
        // This method is invoked on the EDT thread
        JFrame frame = new JFrame("Click here");
        final JFXPanel fxPanel = new JFXPanel();
        frame.add(fxPanel);
        frame.setSize(1000, 700);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                initFX(fxPanel);
            }
        });
    }


    private static Scene getScene() {
        Group  root  =  new  Group();
        Scene  scene  =  new  Scene(root, Color.ALICEBLUE);
        Text  text  =  new  Text();

        text.setX(40);
        text.setY(100);
        text.setFont(new Font(25));
        text.setText("Finally it's working");
        root.getChildren().add(text);

        return (scene);
    }


    private static void initFX(JFXPanel fxPanel) {
        Scene scene = getScene();
        fxPanel.setScene(scene);
    }


    public static void main() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                initAndShowGUI();
            }
        });
    }
}

pom.xml 文件:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.carrier.ccr</groupId>
  <artifactId>test</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <name>test</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
            <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>13</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>13</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-swing</artifactId>
            <version>18-ea+5</version>
        </dependency>
        
  </dependencies>

  <build>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
            <plugin> 
    
               <!-- Building an executable jar -->
    
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-jar-plugin</artifactId>
               <version>3.1.0</version>
               <configuration>
                 <archive>
                   <manifest>
    
                   <!-- give full qualified name of your main class-->
                   <addClasspath>true</addClasspath>
                     <mainClass>com.carrier.ccr.test.App</mainClass>
    
                   </manifest>
                 </archive>
               </configuration>
            </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
        <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
        <plugin>
          <artifactId>maven-site-plugin</artifactId>
          <version>3.7.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-project-info-reports-plugin</artifactId>
          <version>3.0.0</version>
        </plugin>
        
        
      </plugins>
    </pluginManagement>
  </build>
</project>

【问题讨论】:

  • 可能你应该在调用 java -jar 时将依赖项中提到的 jars(至少所有 java-fx jars)添加到你的类路径中。为此使用“-cp”选项。
  • 不要依赖混合版本的 JavaFX 库。如果可以避免,请不要依赖早期访问软件。当前 JavaFX 版本是 17.0.1,将其用于所有 JavaFX 依赖项。

标签: java maven swing javafx executable-jar


【解决方案1】:

您的代码和包装存在许多问题。我现在真的无法在这里解释所有这些。但如果您愿意,我会提出一些您可以尝试使用的替代方案。

我还要添加一个常见的警告:除非你真的必须这样做,否则不要混合使用 JavaFX 和 Swing。

替代包装

自包含选项从最少到最多排序(不是从最可取到最不理想):

  1. Thin jar 没有 JavaFX 依赖项

    • 要求应用程序在包含预捆绑 JavaFX 模块的 JDK 或 Java 运行时上运行。例如,来自下面提到的分销商。如果使用,请确保选择他们的 JDK 发行版,其中 包括 JavaFX

    • 您无需将 JavaFX 依赖项放入 Maven 项目中,因为它们已经在底层平台中可用。

    • 如果是一个简单的应用程序,除了标准的JDK和JavaFX之外没有任何其他依赖,那么你可以将应用程序打包成一个没有依赖关系的可执行jar。

  2. 带阴影的“胖”jar(或 zip)没有 JavaFX 依赖项

    • 如果您有非 javafx 依赖项,您可以使用解决方案中的信息来处理具有 JavaFX 依赖项的“胖”jar 或不带 JRE 的 zip。
      • 不要将 JavaFX 依赖项放在 maven 项目依赖项列表中。
      • 确保您和您的用户始终使用包含 JavaFX 的 JDK 或 java 运行时。
  3. 带阴影的“胖”罐子(jar)带有 JavaFX 依赖项

  4. 不带 JRE 的压缩包(zip、tar、tar.gz、tar.bz2)

  5. 使用 JRE 压缩(zip、tar、tar.gz、tar.bz2)

    • 使用jlink 创建运行时映像目录。
    • 使用assembly 创建运行时映像的 zip。
  6. Windows exe(exe)

  7. 本机安装程序(msi、dmg、app、rpm、deb)

就用户的易用性而言,我建议使用后者捆绑工作 Java 运行时的版本:本机安装程序、带有 JRE 的 Zip 或 Windows exe。

我认为要求用户安装有效 JRE 的解决方案对于许多应用程序来说不太理想。

  • 由于没有捆绑的 JRE,确保正确的 JRE 存在并正确配置的艰巨工作将转移到每个用户而不是开发人员身上。
  • JavaFX 开发团队不支持包含 JavaFX 依赖项的 Maven 阴影“胖”jar 选项。

对于 Maven 用户

  • 可以从OpenJFX JavaFX Maven plugin 调用jlink。
  • jpackage 可以从akman jpackage maven plugin 调用。
    • jpackage也可以创建图片,和jlink一样。
    • 如果创建本机安装程序,我建议让 jpackage 处理链接和打包(如果您不这样做,jpackage 会警告您)。
    • 在windows应用的一些选项上,我发现jlink默认没有将需要的图标放在正确的位置,导致jpackage做链接时没有出现issues奇怪且难以追踪。李>

没有 JRE 选项的压缩

此答案的其余部分仅关注 Zip without JRE 选项。

请参阅答案末尾的自述文件,其中描述了这是什么以及如何使用它。如果它不是您想要的,请忽略它并尝试以其他方式解决您的问题。

解决方案是不是一个可执行的jar。相反,它是以 jar 格式打包的一组 java 模块,通过启动器脚本执行并组装成压缩存档文件。

  • 它要求在目标机器上安装 JRE 17+。

  • 该应用程序仅打包用于在 Intel Mac 上执行(至少当它是在 Intel Mac 上构建时)。

    • 可以为其他平台打包,但不在我在这里讨论的范围内。

SwingJavaFX 集成

解决方案适用于 Swing+JavaFX 应用程序。通常我不会推荐这样的配置,但是在这里展示它是因为这就是问题所要问的。 SwingJavaFX 集成代码遵循 Oracle 教程中提供的结构和指南:Integrating JavaFX into Swing Applications

如果您的应用程序中没有 Swing,请从 Maven 中删除 Swing 应用程序、模块定义中的 javafx.swing 要求和 javafx-swing 依赖项,并重新配置启动器脚本以直接调用 JavaFX HelloApplication 和所有内容在没有 Swing 的情况下,对于纯 JavaFX 应用程序分发也可以正常工作。

文件树

$ tree
├── pom.xml
├── readme.md
└── src
    ├── assembly
    │   └── bin.xml
    └── main
        ├── command
        │   └── swingfx.sh
        ├── java
        │   ├── com
        │   │   └── example
        │   │       └── swingfx
        │   │           ├── HelloApplication.java
        │   │           ├── HelloController.java
        │   │           └── SwingApp.java
        │   └── module-info.java
        └── resources
            └── com
                └── example
                    └── swingfx
                        └── hello-view.fxml

我跳过了提供 JavaFX FXML 和控制器代码,因为它们与解决方案无关,它们只是由您可以在任何基本 FXML 教程中找到的标准代码组成。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>SwingFX</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>SwingFX</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <javafx.version>17.0.1</javafx.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>${javafx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-swing</artifactId>
            <version>${javafx.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <descriptors>
                        <descriptor>src/assembly/bin.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

模块信息.java

module com.example.swingfx {
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.swing;

    opens com.example.swingfx to javafx.fxml;
    exports com.example.swingfx;
}

SwingApp.java

package com.example.swingfx;

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;

import javax.swing.*;
import java.awt.*;

public class SwingApp {

    private static void initAndShowGUI() {
        JFrame frame = new JFrame("Swing Main App JFrame");
        frame.setSize(500, 180);
        frame.setVisible(true);
        frame.setLayout(null);
        frame.setLocation(100, 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Button opens the ServiceTool interface
        JButton toolLauncher = new JButton("Launch JavaFX Tool");
        toolLauncher.setSize(280, 20);
        toolLauncher.setFont(new Font("Arial", Font.PLAIN, 15));
        toolLauncher.setVisible(true);
        toolLauncher.setLocation(10, 100);
        toolLauncher.addActionListener(e -> launchFXTool());
        frame.add(toolLauncher);
    }

    private static void launchFXTool() {
        try {
            // This method is invoked on the EDT thread
            // The method creates a new frame and JavaFX scene whenever it is invoked.
            // If preferred and only one instance is required, then cache the JFrame
            // on first launch, then show and focus the existing JFrame when the tool is relaunched.
            JFrame frame = new JFrame("Swing JFrame with JavaFX scene content");
            final JFXPanel fxPanel = new JFXPanel();
            frame.add(fxPanel);
            frame.setSize(300, 200);
            frame.setVisible(true);

            Platform.runLater(() -> {
                // This logic is invoked on the JavaFX thread
                try {
                    fxPanel.setScene(
                            HelloApplication.createScene()
                    );
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(SwingApp::initAndShowGUI);
    }
}

HelloApplication.java

package com.example.swingfx;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        stage.setTitle("Hello!");
        stage.setScene(createScene());
        stage.show();
    }

    public static Scene createScene() throws IOException {
        FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
        return new Scene(fxmlLoader.load(), 320, 240);
    }

    public static void main(String[] args) {
        launch(args);
    }
}

swingfx.sh

#!/bin/sh
VM_OPTIONS=
DIR=`dirname $0`
MODULE_PATH=$DIR/../lib
MAIN_CLASS=com.example.swingfx/com.example.swingfx.SwingApp 
# if desired you could add a check to ensure a compatible java version is installed and print a friendly error message if not.
# launches a java app with the given vm options and module path, passing the arguments provided to this script to the app.
java $VM_OPTIONS -p $MODULE_PATH -m $MAIN_CLASS "$@"

bin.xml

<assembly>
    <id>bin</id>
    <formats>
        <format>tar.gz</format>
        <format>zip</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <scope>runtime</scope>
            <outputDirectory>lib</outputDirectory>
        </dependencySet>
    </dependencySets>
    <fileSets>
        <fileSet>
            <directory>src/main/command</directory>
            <outputDirectory>bin</outputDirectory>
            <includes>
                <include>*.sh</include>
                <include>*.bat</include>
            </includes>
            <fileMode>0755</fileMode>
        </fileSet>
    </fileSets>
</assembly>

readme.md

与 JavaFX 集成的 Swing 应用程序示例。 该应用程序构建为 Java 模块应用程序。

构建要求

  • Java JDK 17+
  • Maven 3.8+

执行要求

  • Java JRE 17+
  • Mac OS X 英特尔

构建说明

构建并打包应用程序:

mvn package

构建将创建以下文件:

target/SwingFX-1.0-SNAPSHOT-bin.tar.gz

执行说明

  1. 从存档中提取应用程序二进制文件。

    tar xzvf SwingFX-1.0-SNAPSHOT-bin.tar.gz
    
  2. 运行应用程序:

    SwingFX-1.0-SNAPSHOT/bin/swingfx.sh 
    

分发内容

$ tar xvzf SwingFX-1.0-SNAPSHOT-bin.tar.gz 
x SwingFX-1.0-SNAPSHOT/bin/swingfx.sh
x SwingFX-1.0-SNAPSHOT/lib/javafx-controls-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-controls-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-graphics-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-graphics-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-base-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-base-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-fxml-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-fxml-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-swing-17.0.1.jar
x SwingFX-1.0-SNAPSHOT/lib/javafx-swing-17.0.1-mac.jar
x SwingFX-1.0-SNAPSHOT/lib/SwingFX-1.0-SNAPSHOT.jar

疑难解答

如果您看到以下错误,则说明 java 未安装且位于默认路径上:

-bash: java: command not found

如果您看到如下错误:

Caused by: java.lang.module.InvalidModuleDescriptorException: Unsupported major.minor version 61.0

已安装Java但不是Java 17+,您需要将Java安装升级到更高版本,您可以使用java -version查看当前版本

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-16
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 2014-04-01
    • 2017-08-03
    相关资源
    最近更新 更多