资讯详情

资讯详情

Java编译报错‘无效的目标发行版’深度解析与JDK17环境配置指南

1. 这个报错到底在说什么——不是代码写错了是Java世界的“语言版本错配”“Fatal error compiling: 无效的目标发行版: 17” 这行报错我第一次看到时也愣了一下。它不像 NullPointerException 那样直白地告诉你“空指针”也不像 ClassNotFoundException 那样明确说“类找不到”。它用了一种更隐蔽、更让人抓狂的方式在说话你的编译器想用 Java 17 的语法和特性去干活但手头这把“刀”JDK根本磨不到那个锋利度。简单说这不是你写的代码有逻辑错误而是你整个 Java 开发环境的“语言版本协议”崩了。想象一下你拿着一本用简体中文写的《Java 编程思想第5版》却把它交给一个只会读繁体字、且只学过民国时期文言文的老师来批改——老师当然会一脸懵“这字我认识但这句式、这标点、这新词……我根本没法理解” 报错里的“17”就是那本新书要求的“简体中文现代语法”而你本地的 JDK可能还是个只会“繁体文言”的老先生比如 JDK 8 或 JDK 11。这个报错高频出现在mvn compile或mvn clean compile执行时核心矛盾点就卡在 Maven 的maven-compiler-plugin插件上。它默认会读取项目pom.xml里maven.compiler.source和maven.compiler.target的配置告诉编译器“请用 Java 17 的规则来编译”。但如果系统里压根没有安装 JDK 17或者虽然装了但 Maven 根本没找到它或者找到了却因为环境变量混乱而调用了旧版本那编译器就会当场罢工抛出这句冰冷的“无效的目标发行版”。热搜词里反复出现的 “jdk安装”、“jdk环境变量配置失败”、“jdk降级到17”、“找不到jdk”恰恰印证了这个问题的本质它90%以上不是代码问题而是环境治理问题。你不需要重写业务逻辑你需要做的是给你的开发工具链做一次精准的“版本对齐手术”。接下来我会带你一层层剥开这个报错背后的四重迷雾为什么是17为什么Maven会认错JDK为什么环境变量总配不对以及为什么有时候明明装了JDK 17它还是视而不见这些都是我在给二十多个团队做Java环境标准化时踩过最深、也最值得分享的坑。2. 深度拆解报错背后的四重技术迷雾与根源逻辑2.1 为什么偏偏是“17”——Java版本演进与Maven插件的默认行为“17”这个数字绝非偶然。它是 Java 的一个长期支持LTS版本于2021年9月正式发布带来了大量现代化特性密封类Sealed Classes、模式匹配Pattern Matching for switch、新的垃圾回收器ZGC的生产就绪、以及最重要的——对现代CPU指令集如AVX-512的更好支持。正因如此越来越多的新项目、框架如Spring Boot 3.x和IDE如IntelliJ IDEA 2022.3都开始将Java 17作为默认或推荐的最低版本。但关键在于Maven本身并不自带JDK。它只是一个构建工具编译工作实际由JDK里的javac命令完成。maven-compiler-plugin插件的作用就是作为一个“翻译官”把你在pom.xml里写的source和target配置转换成javac命令行参数。例如当你配置properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target /properties插件最终会执行类似这样的命令/usr/lib/jvm/java-17-openjdk-amd64/bin/javac -source 17 -target 17 ...问题就出在这里如果系统里根本没有/usr/lib/jvm/java-17-openjdk-amd64/这个路径或者该路径下的javac是个假链接或者javac实际指向的是 JDK 11 的二进制文件那么-source 17这个参数就会被javac直接拒绝因为它根本不认识“17”这个发行版号。javac的版本号和它能接受的-source参数是严格绑定的。JDK 11 的javac最多只认到-source 11JDK 17 的javac才能处理-source 17。这就是“无效的目标发行版”最底层的原理——一个版本不兼容的硬性约束。2.2 Maven是如何“找”JDK的——从JAVA_HOME到mvn脚本的完整寻址链很多人以为只要设置了JAVA_HOMEMaven 就万事大吉。这是个巨大的误解。Maven 查找 JDK 的过程是一条环环相扣的“寻宝链”任何一个环节出错都会导致它用错JDK。这条链路如下第一优先级mvn脚本内部的硬编码检查在 Linux/macOS 上mvn是一个 shell 脚本在 Windows 上是mvn.cmd。这个脚本开头几行会主动检查几个环境变量# mvn 脚本片段 if [ -z $JAVA_HOME ] ; then JAVA_HOMEdirname $(dirname $(readlink -f $(which java))) fi它会先看JAVA_HOME是否设置。如果没有它会尝试通过which java找到系统java命令的路径然后向上两级目录推导出JAVA_HOME。这意味着如果你的PATH里java指向的是/usr/bin/java而/usr/bin/java又是个软链接指向/etc/alternatives/java再指向/usr/lib/jvm/java-11-openjdk-amd64/bin/java那么 Maven 就会把JAVA_HOME设为/usr/lib/jvm/java-11-openjdk-amd64哪怕你心里想着要用 JDK 17。第二优先级JAVA_HOME环境变量如果你手动设置了JAVA_HOME比如export JAVA_HOME/opt/jdk-17.0.1那么 Maven 会直接使用这个路径。但这里有个致命陷阱JAVA_HOME必须指向 JDK 的根目录而不是bin目录。设成JAVA_HOME/opt/jdk-17.0.1/bin是常见错误会导致 Maven 启动失败。第三优先级MAVEN_OPTS中的-Djava.home你可以通过MAVEN_OPTS-Djava.home/path/to/jdk17来强制指定。这个参数的优先级高于JAVA_HOME但需要每次运行mvn前都设置非常麻烦一般只用于临时调试。第四优先级pom.xml中的maven-compiler-plugin配置这是最容易被忽略的一环。即使你JAVA_HOME设置正确mvn也确实调用了 JDK 17 的javac但如果pom.xml里没配置source和targetMaven 插件会使用自己的默认值。而这个默认值在较老版本的maven-compiler-plugin如3.1中是1.5也就是说它会用 JDK 17 去编译一个要求兼容 Java 1.5 的代码这本身不会报错。但如果你升级了插件比如到3.10它的默认值就变成了8或11。此时如果你的代码里用了var关键字Java 10 引入或switch表达式Java 14而插件默认只认11它就会报错。所以显式配置source和target不仅是为了指定版本更是为了切断插件默认值带来的不确定性。2.3 环境变量为何总配不对——PATH、JAVA_HOME 与 Shell 初始化的隐秘战争JAVA_HOME和PATH的配置是Linux/macOS下最经典的“薛定谔的环境变量”问题。你明明在~/.bashrc里写了export JAVA_HOME...source ~/.bashrc之后echo $JAVA_HOME也显示正确但一打开新终端或者运行mvn它又变回了旧版本。原因在于 Shell 的初始化流程。Bash 有四种启动模式登录Shell、非登录Shell、交互式、非交互式。它们读取的初始化文件完全不同登录Shell如你SSH登录、或图形界面下打开终端依次读取/etc/profile→~/.bash_profile→~/.bash_login→~/.profile。非登录交互式Shell如你在已打开的终端里再开一个bash只读取~/.bashrc。而mvn命令通常是在非登录Shell里执行的它只认~/.bashrc。如果你把JAVA_HOME写在了~/.bash_profile里那么mvn就永远看不到它。这就是为什么很多人“配了又配还是不行”的根本原因。更复杂的是很多发行版如Ubuntu的~/.bashrc文件末尾有一段注释掉的代码# If not running interactively, dont do anything case $- in *i*) ;; *) return;; esac这段代码确保了~/.bashrc只在交互式Shell里执行。而某些CI/CD工具如Jenkins启动的Shell是非交互式的它会跳过~/.bashrc直接去找~/.profile。所以最稳妥的做法是把JAVA_HOME和PATH的设置同时放在~/.bash_profile和~/.bashrc的末尾并确保它们内容一致。这样无论哪种Shell启动都能加载到正确的环境。2.4 为什么“明明装了JDK 17它还是视而不见”——多版本共存下的路径幻觉在企业开发环境中一台机器上同时装着 JDK 8、11、17 甚至 21 是常态。这时which java命令返回的结果往往只是PATH中第一个找到的java它可能指向/usr/bin/java而/usr/bin/java又是一个由update-alternatives管理的符号链接。update-alternatives是一个Linux工具它允许你为同一个命令如java注册多个版本并通过一个统一的入口来切换。你可以用sudo update-alternatives --config java来查看所有已注册的JDK版本并选择当前默认的。但问题在于mvn脚本在查找JDK时有时会绕过update-alternatives直接去读取JAVA_HOME或PATH。这就造成了“幻觉”你用java -version看到的是17但mvn compile却报17无效。因为mvn没有走update-alternatives这条路它走的是自己的寻址链。解决这个问题的终极方案是放弃依赖update-alternatives的全局切换转而为每个项目或每个Shell会话精确地、显式地指定JAVA_HOME。这听起来很笨重但在多版本、多项目并行的现实世界里它反而是最可靠、最可预测的方法。这也是为什么像 SDKMAN! 这样的工具如此流行——它本质上就是帮你自动化地、安全地管理JAVA_HOME的切换。3. 实操指南从零开始四步构建一个坚不可摧的 JDK 17 Maven 环境3.1 第一步下载与安装 JDK 17 —— 选对镜像源避开官方慢速陷阱JDK 17 的官方下载地址是https://adoptium.net/原 AdoptOpenJDK但国内用户直接访问速度往往令人绝望。这时候国内镜像源就是救命稻草。根据我的实测以下三个镜像源速度和稳定性最佳镜像源地址特点推荐场景清华大学TUNAhttps://mirrors.tuna.tsinghua.edu.cn/adoptium/更新及时带校验码支持HTTP/HTTPS通用首选适合所有用户华为云https://repo.huaweicloud.com/java/CDN加速下载极快对速度要求极高如CI/CD流水线阿里云https://mirrors.aliyun.com/java-openjdk/稳定性好偶尔更新稍慢企业内网部署追求稳定下载步骤以Linux x64为例打开清华镜像站https://mirrors.tuna.tsinghua.edu.cn/adoptium/17/jdk/x64/找到最新版本的.tar.gz包例如EclipseTemurinJDK-17.0.1_12-linux-x64.tar.gz。使用wget下载比浏览器下载更可靠wget https://mirrors.tuna.tsinghua.edu.cn/adoptium/17/jdk/x64/EclipseTemurinJDK-17.0.1_12-linux-x64.tar.gz解压到一个固定、无空格、无特殊字符的路径例如/opt/jdk-17.0.1sudo mkdir -p /opt/jdk-17.0.1 sudo tar -xzf EclipseTemurinJDK-17.0.1_12-linux-x64.tar.gz -C /opt/jdk-17.0.1 --strip-components1提示--strip-components1参数非常重要。它会把解压出来的jdk-17.0.112这个顶层目录去掉直接把内容放到/opt/jdk-17.0.1下。否则你会得到/opt/jdk-17.0.1/jdk-17.0.112/路径太深容易出错。验证安装/opt/jdk-17.0.1/bin/java -version # 输出应为openjdk version 17.0.1 2021-10-193.2 第二步配置环境变量 —— 一次写对永久生效现在我们要让系统“记住”这个新家。编辑~/.bashrc如果你用的是Zsh则编辑~/.zshrc# 在文件末尾添加以下三行 export JAVA_HOME/opt/jdk-17.0.1 export PATH$JAVA_HOME/bin:$PATH export JRE_HOME$JAVA_HOME/jre注意JRE_HOME虽然在现代JDK中已不常用JDK 9 合并了JRE但某些老旧的脚本或工具如Tomcat仍会读取它设上更保险。然后立即生效source ~/.bashrc验证是否成功echo $JAVA_HOME # 应输出 /opt/jdk-17.0.1 java -version # 应输出 JDK 17 的版本信息 which java # 应输出 /opt/jdk-17.0.1/bin/java提示如果你发现which java依然指向/usr/bin/java说明你的PATH里有其他路径排在$JAVA_HOME/bin前面。用echo $PATH查看确保$JAVA_HOME/bin是第一个。3.3 第三步配置 Maven —— 让构建工具“认祖归宗”Maven 的配置分为两层全局配置和项目配置。全局配置推荐编辑 Maven 的全局配置文件~/.m2/settings.xml如果不存在就创建一个。在profiles标签下添加一个针对 JDK 17 的 profilesettings xmlnshttp://maven.apache.org/SETTINGS/1.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd profiles profile idjdk-17/id activation activeByDefaulttrue/activeByDefault /activation properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target maven.compiler.release17/maven.compiler.release /properties /profile /profiles /settingsmaven.compiler.release是一个关键参数。它等价于同时设置-source和-target并且还会启用-bootclasspath确保编译出的字节码完全兼容指定的JDK版本不会意外引用到高版本才有的API。这是比单纯设置source/target更严格的“兼容性锁”。项目配置必须在你的项目pom.xml的properties部分必须再次声明覆盖任何可能的全局默认值properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target maven.compiler.release17/maven.compiler.release !-- 显式指定插件版本避免使用Maven内置的老旧版本 -- maven-compiler-plugin.version3.11.0/maven-compiler-plugin.version /properties build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version${maven-compiler-plugin.version}/version /plugin /plugins /build实操心得我曾经在一个客户现场发现他们所有项目的pom.xml都没配source/target全靠全局settings.xml。结果某天运维升级了Maven新版本的内置插件默认值变成了11导致所有新提交的、用了var的代码全部编译失败。从此以后我坚持“项目级配置优先”把pom.xml当作项目唯一的真相来源。3.4 第四步终极验证与一键诊断脚本一切配置完成后不要急着跑mvn compile先用一个简单的诊断脚本来确认所有环节都畅通无阻#!/bin/bash # save as check-jdk-env.sh echo 1. 检查 JAVA_HOME echo JAVA_HOME: $JAVA_HOME if [ -z $JAVA_HOME ]; then echo ❌ ERROR: JAVA_HOME is not set! exit 1 fi echo 2. 检查 java 命令 JAVA_CMD$(which java) echo which java: $JAVA_CMD if [ ! -f $JAVA_CMD ]; then echo ❌ ERROR: java command not found in PATH! exit 1 fi echo 3. 检查 java 版本 $JAVA_CMD -version 21 | head -1 echo 4. 检查 javac 命令 JAVAC_CMD$(which javac) echo which javac: $JAVAC_CMD if [ ! -f $JAVAC_CMD ]; then echo ❌ ERROR: javac command not found in PATH! exit 1 fi echo 5. 检查 javac 版本 $JAVAC_CMD -version 21 echo 6. 检查 Maven 使用的 JDK echo Maven will use: $(mvn -v | grep Java version) echo ✅ All checks passed. Your environment is ready for JDK 17.给脚本加上执行权限并运行chmod x check-jdk-env.sh ./check-jdk-env.sh如果所有检查都通过那么最后一步就是用一个最小化的pom.xml来进行终极验证?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion groupIdtest/groupId artifactIdjdk17-test/artifactId version1.0-SNAPSHOT/version properties maven.compiler.source17/maven.compiler.source maven.compiler.target17/maven.compiler.target maven.compiler.release17/maven.compiler.release /properties build plugins plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version /plugin /plugins /build /project创建一个src/main/java/App.javapublic class App { public static void main(String[] args) { // 使用 Java 17 特性局部变量类型推断 var message Hello, JDK 17!; System.out.println(message); } }然后执行mvn clean compile如果看到[INFO] BUILD SUCCESS恭喜你你已经成功驯服了这个“无效的目标发行版”报错。你构建的不再是一个脆弱的、依赖运气的环境而是一个可复现、可验证、可交付的开发基石。4. 常见问题与排查技巧实录那些让我熬夜到凌晨三点的坑4.1 问题现象mvn -v显示 JDK 17但mvn compile依然报错排查思路mvn -v显示的是 Maven 自身运行时的 JDK而mvn compile调用的是javac。这两者可以是不同的JDKMaven自身可以用 JDK 11 启动但它调用的javac却可以是 JDK 17。反之亦然。诊断方法在mvn compile命令前加上-X参数开启Debug模式mvn compile -X | grep Using Java你会看到类似这样的输出[DEBUG] Using Java version: 11.0.18 (vendor: Ubuntu, location: /usr/lib/jvm/java-11-openjdk-amd64)这行日志里的location就是javac的真实路径。它和mvn -v里显示的JAVA_HOME很可能不一样。解决方案强制让 Maven 使用你指定的 JDK 来执行编译任务。在pom.xml的maven-compiler-plugin配置中添加fork和executableplugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-compiler-plugin/artifactId version3.11.0/version configuration forktrue/fork executable/opt/jdk-17.0.1/bin/javac/executable source17/source target17/target release17/release /configuration /pluginforktrue/fork表示让 Maven 启动一个独立的 JVM 进程来执行javacexecutable则精确指定了这个进程要使用的javac二进制文件。这是最暴力、但也最有效的“一锤定音”方案。4.2 问题现象在 IntelliJ IDEA 里编译成功但命令行mvn compile失败根本原因IDEA 是一个独立的Java应用它有自己的JDK配置File → Project Structure → Project → Project SDK它完全不关心你的系统JAVA_HOME或PATH。它用自己的SDK去编译所以成功。而命令行mvn则完全遵循我们前面讲的那套寻址链所以失败。解决方案这是一个典型的“环境割裂”问题。最优雅的解决方式是让 IDEA 的项目配置与命令行环境保持一致。在 IDEA 的pom.xml编辑器里右键 →Reload project这会让 IDEA 重新读取pom.xml里的maven-compiler-plugin配置并自动同步到其内部的编译器设置。如果这招不行就手动在 IDEA 的Settings → Build → Compiler → Java Compiler里将Project bytecode version和Target bytecode version都设为17。4.3 问题现象mvn clean compile -DskipTests成功但mvn test失败报同样的“无效的目标发行版”深层解析mvn test阶段不仅会编译测试代码还会运行测试。运行测试需要一个 JVM而这个 JVM 的版本是由maven-surefire-plugin插件控制的。这个插件也有自己的jvm配置。解决方案在pom.xml中为maven-surefire-plugin添加 JVM 配置plugin groupIdorg.apache.maven.plugins/groupId artifactIdmaven-surefire-plugin/artifactId version3.0.0-M9/version configuration jvm/opt/jdk-17.0.1/bin/java/jvm argLine--add-opens java.base/java.langALL-UNNAMED/argLine /configuration /pluginjvm参数指定了运行测试时使用的java命令。argLine里的--add-opens是 Java 17 的模块化系统要求用于解决反射相关的访问限制这是另一个常被忽略的细节。4.4 问题现象在 Docker 容器里构建失败报错相同典型场景你写了一个Dockerfile里面FROM maven:3.8.6-openjdk-11然后COPY . .最后RUN mvn clean compile。容器里只有 JDK 11但你的pom.xml要求 JDK 17自然失败。标准解法不要用maven:xxx-openjdk-xx这种预装了JDK的镜像而是用maven:3.8.6-openjdk-17或者更推荐的用maven:3.8.6-openjdk-17-slim体积更小。如果官方没有你需要的版本就自己构建FROM maven:3.8.6-openjdk-17-slim # 将你的项目复制进来 COPY . /workspace WORKDIR /workspace # 运行构建 RUN mvn clean compile -DskipTests高级技巧多阶段构建如果你的项目最终要打包成一个 Spring Boot 的 fat jar你可以用多阶段构建让构建阶段用 JDK 17而运行阶段用更轻量的 JRE# 构建阶段 FROM maven:3.8.6-openjdk-17-slim AS builder COPY pom.xml . RUN mvn dependency:go-offline COPY . . RUN mvn clean package -DskipTests # 运行阶段 FROM openjdk:17-jre-slim COPY --frombuilder /workspace/target/*.jar app.jar ENTRYPOINT [java,-Djava.security.egdfile:/dev/./urandom,-jar,/app.jar]这样你的最终镜像里只包含运行时必需的 JRE 17没有庞大的 Maven 和 JDK 17 的开发工具链体积能减少 70% 以上。4.5 问题现象公司内网无法访问外部镜像源如何离线安装 JDK 17实战方案离线安装的核心是把 JDK 的二进制包和所有依赖打包成一个可移动的“环境胶囊”。在一台能上网的机器上下载 JDK 17 的.tar.gz包。下载 Maven 的二进制包https://dlcdn.apache.org/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.tar.gz。创建一个env-setup.sh脚本#!/bin/bash # 解压 JDK tar -xzf jdk-17.0.1_linux-x64_bin.tar.gz -C /opt/ # 解压 Maven tar -xzf apache-maven-3.8.6-bin.tar.gz -C /opt/ # 创建软链接方便后续升级 sudo ln -sf /opt/jdk-17.0.1 /opt/jdk sudo ln -sf /opt/apache-maven-3.8.6 /opt/maven # 配置环境变量 echo export JAVA_HOME/opt/jdk /etc/profile.d/java.sh echo export MAVEN_HOME/opt/maven /etc/profile.d/java.sh echo export PATH$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH /etc/profile.d/java.sh source /etc/profile.d/java.sh将jdk-17.0.1_linux-x64_bin.tar.gz、apache-maven-3.8.6-bin.tar.gz和env-setup.sh一起打包成一个.zip文件。在目标内网机器上解压并运行unzip jdk-maven-offline.zip chmod x env-setup.sh sudo ./env-setup.sh这个方案我已经在三家金融客户的内网环境中成功部署过。它把一个复杂的环境配置过程压缩成了一条sudo ./env-setup.sh命令彻底消除了人为配置错误的风险。5. 经验总结从“救火队员”到“环境架构师”的思维跃迁在我刚入行的头两年每次遇到“Fatal error compiling: 无效的目标发行版”我的第一反应就是百度、Stack Overflow然后机械地复制粘贴别人的解决方案改JAVA_HOME、改pom.xml、改settings.xml……就像一个在火场里到处找水龙头的消防员忙得满头大汗却不知道火源在哪里。直到有一次我负责给一个大型微服务集群做 JDK 升级。我们有 50 多个服务每个服务的pom.xml都千差万别有的配了source/target有的没配有的用的是maven-compiler-plugin2.x有的是 3.x。当我粗暴地把所有pom.xml都改成17后CI 流水线瞬间崩溃一半的服务编译失败。那一刻我才明白环境问题从来不是一个孤立的“错误”而是一个系统性的“契约”问题。Java 的版本是代码、构建工具、运行时、IDE、CI/CD 平台之间的一份隐形契约。这份契约规定了代码能用什么语法、构建工具用哪个javac、运行时能加载哪些字节码、IDE 用哪个 SDK 进行语法检查。当契约的任何一方违约整个系统就会发出警报而“无效的目标发行版”就是最响亮的警报声。所以我现在处理这类问题的思路已经从“怎么修”升级到了“怎么防”防御性编码在每个新项目的pom.xml模板里强制包含source/target/release的配置并将其作为代码审查Code Review的必检项。一个没有显式声明 JDK 版本的pom.xml是不合格的。基础设施即代码IaC把 JDK 和 Maven 的安装、配置全部写成 Ansible Playbook 或 Shell 脚本。每一次新服务器上线都执行同一份脚本确保环境的 100% 一致性。人会犯错但脚本不会。可观测性建设在 CI/CD 流水线的每个构建步骤前都插入一个check-jdk-env.sh脚本。它会输出当前JAVA_HOME、java -version、javac -version和mvn -v的完整信息并将其作为构建日志的一部分存档。当问题发生时你不再需要问“你那边是什么版本”日志里一目了然。最后我想分享一个我自己的小技巧。我把所有常用的 JDK 版本都安装在/opt/jdk/目录下并用软链接来管理/opt/jdk/ ├── jdk8 - /opt/jdk-8u292 ├── jdk11 - /opt/jdk-11.
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →