java应用打包运行的4种方法

文章目录

    • 1、方法一:打成jar部署运行
    • 2、方法二:通过自制启动器的方式运行
    • 3、方法三:使用jpackage把java和jdk一起打包
    • 4、方法四:使用GraalVM编译为原生应用
      • 4.1、使用native-image-agent(Graalvm内工具)工具来收集这些运行库信息
      • 4.2、编译为原生应用,Window平台下为DFDiff.exe,Linux平台上为DFDiff
      • 4.3、把console程序转为GUI程序
      • 4.4、添加应用图标
      • 4.5、编译后文件
        • 4.5.1、Windows平台编译后得到的运行文件
        • 4.5.2、Linux平台编译后得到的运行文件
    • 5、小结
    • 6、附录jpackage参数
      • 6.1、通用选项
      • 6.2、用于创建运行时映像的选项
      • 6.3、用于创建应用程序映像的选项
      • 6.4、用于创建应用程序启动器的依赖于平台的选项:
      • 6.5、用于创建应用程序包的选项:
      • 6.6、用于创建应用程序包的与平台相关的选项:
      • 6.7、jpackage 示例

本文主要介绍java应用编译打包后运行的方法。
本文以DFDiff:( https://gitee.com/penngo/dfdiff)项目为例子,介绍打包运行的方法

使用maven生成jar包:DFDiff-1.2.0-jar-with-dependencies.jar

mvn package

1、方法一:打成jar部署运行

这个方法需要单独安装JDK,然后在命令行下启动,可以单独制作启动脚本。
window下bat启动脚本

# 1、如果依赖包也打成同一个jar
@echo off
@REM 如果没有设置系统环境变量,如果在脚本中指定JDK
SET JAVA_HOME=C:\Program Files\Java\bellsoft\jdk-17.0.9
SET PATH=%JAVA_HOME%/bin;%PATH%;

@REM 936设为GBK编译, 65001设为UTF编译
chcp 65001  
java -jar DFDiff-1.2.0-jar-with-dependencies.jar


# 2、如果依赖包独立,本文不使用该方法,仅供打包其它项目时参考
@rem windows
@echo off
set project_home=%~dp0
echo %project_home%
setlocal enabledelayedexpansion
SET class_path=%project_home%DFDiff-1.2.0-jar-with-dependencies.jar
for /r %project_home%/lib %%i in (*.jar) do (
	rem echo %%i
	set class_path=!class_path!;%%i
)
echo %class_path%
java -Xms512m -Xmx512m -classpath %class_path% com.penngo.gui.dfdiff.DFMain
rem pause

Linux下shell启动脚本

# 1、如果依赖包也打成同一个jar
export JAVA_HOME=/usr/lib/jvm/bellsoft-java17.x86_64
export PATH=$JAVA_HOME/bin:$PATH
java -jar DFDiff-1.2.0-jar-with-dependencies.jar

# 2、如果依赖包独立,本文不使用该方法,仅供打包其它项目时参考
export JAVA_HOME=/usr/lib/jvm/bellsoft-java17.x86_64
export PATH=$JAVA_HOME/bin:$PATH

cd `dirname $0`
echo `pwd`

class_name=com.penngo.gui.dfdiff.DFMain
project_home=$(pwd)
class_path=
function libjars(){
for file in $project_home/lib/*
do
if [ -f $file ]
then
 #echo $file   
 class_path="$class_path$file:"
fi
done
}

libjars
class_path="$class_path:$project_home/DFDiff-1.2.0-jar-with-dependencies.jar"
export CLASSPATH=$CLASSPATH:$class_path
java -Xms512m -Xmx512m -Dproject.dir="$project_home" $class_name

2、方法二:通过自制启动器的方式运行

本文使用go来制作启动器,也可以使用其它能编译为原生应用的语言(C/C++,rust等)来制作,启动器的主要用来代替Window/Linux的shell脚本来启动java应用,
main.go源码

package main
import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
)

func main() {
	var cmd *exec.Cmd
	fmt.Println("GOOS====", runtime.GOOS)
	if runtime.GOOS == "windows" {
	    // window下调用java启动
		cmd = exec.Command("jbr\\bin\\java.exe", "-jar", "DFDiff-1.2.0-jar-with-dependencies.jar")

	} else {
	    // 其它平台,Linux下调用java启动
		cmd = exec.Command("jbr/bin/java", "-jar", "DFDiff-1.2.0-jar-with-dependencies.jar")
	}
	cmd.Stdout = os.Stdout
	if err := cmd.Run(); err != nil {
		fmt.Println("could not run command: ", err)
	}
}

执行编译命令,生成可执行程序

go build main.go

window下生成main.exe运行程序,linux下生成main运行程序
默认下生成命令行下运行的控制台程序,运行时会带一个黑色命令行窗体。
window下转换为桌面应用和添加图标的方法

# winodw:console转为GUI, 
editbin /subsystem:windows main.exe

# winodw:添加图标
RCEDIT.exe /I main.exe logo.ico

editbin工具:https://learn.microsoft.com/zh-cn/cpp/build/reference/editbin-options?view=msvc-160
RCEDIT工具:https://github.com/poidasmith/winrun4j/releases/

使用jlink生成运行时(精简JRE)

# window下用jlink.exe,Linux下用jlink
jlink.exe --module-path jmods --add-modules java.desktop,java.logging,jdk.management,java.sql --output jbr

windown最终生成目录如下:linux下目录类似,只是对应的运行程序没有.exe后缀
在这里插入图片描述

window下双击main.exe运行,Linux下双击main程序运行

3、方法三:使用jpackage把java和jdk一起打包

jpackage是JDK14后新增的独立打包的工具,同时会借助jlink工具按模块需要生成精简的JRE(java运行时),执行下边命令生成

jpackage --type app-image --name DFDiff --input target --app-version 1.2.0 --copyright gitee.com/penngo --vendor gitee.com/penngo --icon logo.ico --add-modules java.desktop,java.logging,jdk.management,java.sql --main-jar DFDiff-1.2.0-jar-with-dependencies.jar --dest dist

window下执行jpackage后生成的文件,双击DFDiff.exe运行
在这里插入图片描述

Linux下执行jpackage后生成的文件,shell环境下输入命令./DFDiff运行
在这里插入图片描述

4、方法四:使用GraalVM编译为原生应用

4.1、使用native-image-agent(Graalvm内工具)工具来收集这些运行库信息

java -agentlib:native-image-agent=config-output-dir=META-INF/native-image -jar DFDiff-1.0.0-jar-with-dependencies.jar
# 或
mvn -Pnative -Dagent exec:exec@java-agent

4.2、编译为原生应用,Window平台下为DFDiff.exe,Linux平台上为DFDiff

native-image --verbose --no-fallback -H:ConfigurationFileDirectories=META-INF/native-image --link-at-build-time --allow-incomplete-classpath -jar DFDiff-1.0.0-jar-with-dependencies.jar DFDiff
# 或
mvn -DskipTests=true -Pnative -Dagent package

4.3、把console程序转为GUI程序

Grallvm编译后的原生应用默认为控制台运行,window下运行时带黑色窗体,可以通过以下命令转为GUI程序。
editbin使用介绍:https://learn.microsoft.com/zh-cn/cpp/build/reference/editbin-options?view=msvc-160

editbin /subsystem:windows DFDiff.exe

4.4、添加应用图标

window下修改应用图标可以使用第三方工具WinRun4J:https://github.com/poidasmith/winrun4j

RCEDIT.exe /I DFDiff.exe logo.ico

4.5、编译后文件

4.5.1、Windows平台编译后得到的运行文件

在这里插入图片描述

4.5.2、Linux平台编译后得到的运行文件

在这里插入图片描述

5、小结

  • 方法一是打成Jar,使用shell脚本启动是最常用的打包运行方式,打包发布不会存在兼容问题。运行时会显示两个进程:shell进程与java进程。
  • 方法二是在方法一基础上,简化shell的启动方式,但是启动器需要在每个平台上编译一次。运行时会显示两个进程:启动器进程与java进程。
  • 方法三是JDK自带的工具打包,与方法二相比,省掉自己编写启动器的工具。运行时会显示两个相同名称的应用进程。
  • 方法四是目前新的方式,能显著提高性能,但由于应用使用反射等技术原因,可能需要手动编写反射类,与前边3种方法相比,有一点的上手难度,同样也由此造成与前边三个方法相比,兼容性相对差。运行时只显示一个进程。

6、附录jpackage参数

6.1、通用选项

--type-t <键入字符串>
#要创建的包的类型
#有效值为:{"app-image", "exe", "msi", "rpm", "deb", "pkg", "dmg"}
#如果未指定此选项,则将创建一个与平台相关的默认类型。

--app-version <版本>
#应用程序和/或软件包的版本

--copyright <版权字符串>
#应用程序的版权。

--description <说明字符串>
#应用程序的说明。

--help-h
#将包含当前平台的每个有效选项的列表和说明的用法文本打印到输出流中,然后退出。

--name-n <name>
#应用程序和/或程序包的名称。

--dest-d <输出路径>
#生成输出文件的放置路径
#默认为当前工作目录。(绝对路径或相对于当前目录)。

--temp <文件路径>
#用于创建临时文件的新目录或空目录的路径(绝对路径或相对于当前目录的路径)。
#如果指定,则在任务完成时不会删除临时目录,必须手动删除。
#如果未指定,则在任务完成后将创建并删除临时目录。

--vendor <字符串>
#应用程序的供应商。

--verbose
#启用详细输出。

--version
#将产品版本打印到输出流并退出。 作者:蔡广 https://www.bilibili.com/read/cv14523427/ 出处:bilibili

6.2、用于创建运行时映像的选项

--add-modules <模块名称> [<模块名称>...],
#以逗号 (",") 分隔的要添加的模块列表。
#此模块列表以及主模块(如果指定)将作为 --add-module 参数传递给 jlink。如果未指定,则仅使用主模块(如果指定了 --module)或默认模块集(如果指定了 --main-jar)。
#此选项可以多次使用。

--module-path 或 -p <模块路径>...
#文件.路径分隔符分隔的路径列表。
#每个路径要么是模块的目录,要么是模块化 jar 的路径,并且是绝对的或相对于当前目录的。
#此选项可以多次使用。

--jlink-options <jlink选项>
#要传递给 jlink 的以空格分隔的选项列表
#如果未指定,则默认为"--strip-native-commands --strip-debug --no-man-pages --no-header-files"
#此选项可以多次使用。

--runtime-image <文件路径>
#将复制到应用程序映像中的预定义运行时映像的路径(绝对路径或相对于当前目录的路径)。
#如果未指定 --runtime-image,jpackage 将运行 jlink 以使用以下选项创建运行时映像:--strip-debug、--no-header-files、--no-man-pages 和 --strip-native-commands。 

6.3、用于创建应用程序映像的选项

--icon<图标文件路径>
#应用程序捆绑包图标的路径(绝对路径或相对于当前目录的路径)。

--input-i <输入路径>
#包含要打包的文件的输入目录的路径(绝对路径或相对于当前目录的路径)。
#输入目录中的所有文件都将打包到应用程序映像中。
用于创建应用程序启动器的选项:
--add-launcher <启动器名称>=<文件路径>
#启动器的名称,以及包含键、值对列表(绝对路径或相对于当前目录)的属性文件的路径。
#可以使用键"模块","添加模块","主jar","主类","参数","java选项","应用程序版本","图标"和"win-console"。
#这些选项将添加到原始命令行选项中,或用于覆盖原始命令行选项,以生成其他备用启动器。主应用程序启动器将从命令行选项构建。可以使用此选项构建其他替代启动器,并且可以多次使用此选项来构建多个其他启动器。

--arguments <主类参数>
#如果没有向启动器提供命令行参数,则传递给主类的命令行参数。
#此选项可以多次使用。

--java-options <java选项>
#要传递给 Java 运行时的选项。
#此选项可以多次使用。

--main-class <类名>
#要执行的应用程序主类的限定名称。
#仅当指定了 --main-jar 时,才能使用此选项。

--main-jar <jar文件>
#应用程序的主 JAR;包含主类(指定为相对于输入路径的路径)。
#可以指定 --module 或 --main-jar 选项,但不能同时指定两者。

--module-m <模块名称>/<主类>]
#应用程序的主模块(以及可选的主类) 此模块必须位于模块路径上。
#指定此选项后,主模块将在 Java 运行时映像中链接。可以指定 --module 或 --main-jar 选项,但不能同时指定两者。

6.4、用于创建应用程序启动器的依赖于平台的选项:

Windows 平台选项(仅在 Windows 上运行时可用):

--win-console
#为应用程序创建控制台启动器,应为需要控制台交互的应用程序指定启动器

macOS 平台选项(仅在 macOS 上运行时可用):

--mac-package-identifier <ID 字符串>
#唯一标识适用于 macOSX 的应用程序的标识符。
#默认为主类名。
#只能使用字母数字 (A-Z、a-z、0-9)、连字符 (-) 和句点 (.) 字符。

--mac-package-name <名称字符串>
#应用程序在菜单栏中显示的名称。
#这可能与应用程序名称不同。
#此名称的长度必须少于 16 个字符,并且适合在菜单栏和应用程序"信息"窗口中显示。默认为应用程序名称。

--mac-bundle-signing-prefix <前缀字符串>
#对应用程序捆绑包进行签名时,此值将作为所有需要签名且没有现有捆绑包标识符的组件的前缀。

--mac-sign
#请求对捆绑包进行签名。

--mac-signing-keychain <文件路径>
#用于搜索签名标识的钥匙串的路径(绝对路径或相对于当前目录的路径)。
#如果未指定,则使用标准钥匙串。

--mac-signing-key-user-name <团队名称>
#Apple 签名身份名称中的团队名称部分。
#例如"开发者 ID 应用程序:<团队名称>"

6.5、用于创建应用程序包的选项:

--app-image <文件路径>
#用于生成可安装包的预定义应用程序映像的位置(绝对路径或相对于当前目录)。
#请参阅创建应用映像模式选项以创建应用程序映像。

--file-associations <文件路径>
#包含键、值对列表(绝对路径或相对于当前目录)的属性文件的路径。
#键"扩展","哑剧类型","图标"和"描述"可用于描述关联。
#此选项可以多次使用。

--install-dir <文件路径>
#OS X 或 Linux 上应用程序安装目录的绝对路径。应用程序的安装位置的相对子路径,例如 Windows 上的"程序文件"或"AppData"。

--license-file <文件路径>
#许可证文件的路径(绝对路径或相对于当前目录的路径)。

--resource-dir <路径>
#覆盖 jpackage 资源的路径(绝对路径或相对于当前目录的路径)。
#jpackage 的图标、模板文件和其他资源可以通过向此目录添加替换资源来覆盖。

--runtime-image <文件路径>
#要安装的预定义运行时映像的路径(绝对路径或相对于当前目录的路径)。
#创建运行时安装程序时需要该选项。

6.6、用于创建应用程序包的与平台相关的选项:

Windows 平台选项(仅在 Windows 上运行时可用):

--win-dir-chooser
#添加一个对话框,使用户能够选择安装产品的目录。

--win-menu
#将应用程序添加到系统菜单。

--win-menu-group <菜单组名称>
#此应用程序所在的"开始"菜单组。

--win-per-user-install
#请求基于每个用户执行安装。

--win-shortcut
#为应用程序创建桌面快捷方式。

--win-upgrade-uuid <id 字符串>
#与此程序包的升级关联的 UUID

Linux 平台选项(仅在 Linux 上运行时可用):

--linux-package-name <包名称>
#Linux 包的名称,默认为应用程序名称。

--linux-deb-maintainer <电子邮件地址>
#捆绑包.deb维护者。

--linux-menu-group <菜单组名称>
#此应用程序所在的菜单组。

--linux-package-deps
#应用程序所需的包或功能

--linux-rpm-license-type <键入字符串>
#许可证类型(RPM .spec 的"许可证:<值>")。

--linux-app-release <发布字符串>
#RPM 的发布值<name>.spec 文件或 DEB 控制文件的 Debian 修订版值。

--linux-app-category <类别字符串>
#RPM <name>.spec 文件或 DEB 控制文件的节值的组值。

--linux-shortcut
#为应用程序创建快捷方式

6.7、jpackage 示例

#生成适合宿主系统的应用包:
#对于模块化应用:
jpackage -n name -p modulePath -m moduleName/className
#对于非模块化应用程序:
jpackage -i inputDir -n name  --main-class className --main-jar myJar.jar
#从预先构建的应用程序映像:
jpackage -n name --app-image appImageDir

#生成应用镜像:
#对于模块化应用:
jpackage --type app-image -n name -p modulePath -m moduleName/className
#对于非模块化应用程序:
jpackage --type app-image -i inputDir -n name --main-class className --main-jar myJar.jar
#要为 jlink 提供您自己的选项,请单独运行 jlink:
jlink --output appRuntimeImage -p modulePath -m moduleName --no-header-files [<additional jlink options>...]
jpackage --type app-image -n name -m moduleName/className --runtime-image appRuntimeImage

#生成 Java 运行时包:
jpackage -n name --runtime-image <runtime-image> 

参考自官方:https://docs.oracle.com/en/java/javase/17/docs/specs/man/jpackage.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/235155.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件无线电SDR-频谱采集python实现

sdr做的频谱采集&#xff0c;保存的500张频谱图&#xff0c;能看出来是什么东西吗&#xff1f;

成都工业学院Web技术基础(WEB)实验四:CSS3布局应用

写在前面 1、基于2022级计算机大类实验指导书 2、代码仅提供参考&#xff0c;前端变化比较大&#xff0c;按照要求&#xff0c;只能做到像&#xff0c;不能做到一模一样 3、图片和文字仅为示例&#xff0c;需要自行替换 4、如果代码不满足你的要求&#xff0c;请寻求其他的…

perl使用Archive::Tar模块进行文件打包

使用perl的Archive::Tar 模块打包文件夹中的指定文件&#xff0c;输出格式 .tar.gz 。下面是perl代码&#xff1a; #! /usr/bin/perl use v5.14; use File::Find; use Archive::Tar;my filesArry (); my $callback sub {push filesArry, $File::Find::name if -f; };find($c…

【Hive】启动beeline连接hive报错解决

1、解决报错2、在datagrip上连接hive 1、解决报错 刚开始一直报错&#xff1a;启动不起来 hive-site.xml需要配置hiveserver2相关的 在hive-site.xml文件中添加如下配置信息 <!-- 指定hiveserver2连接的host --> <property><name>hive.server2.thrift.bin…

如何打印富文本控件中的内容?

出于某种原因&#xff0c;人们确实对打印富文本控件中的内容感到困惑。 我并非打印方面的专家&#xff0c;但是经过对资料的研究的&#xff0c;我也算弄明白了&#xff0c;今天在此记录一下。 解决问题的关键是这个消息&#xff1a;EM_FORMATRANGE。 每次发送这个消息的时候&a…

Vue 3项目的目录结构

使用vite创建完VUE项目后&#xff0c;使用VS Code编辑器打开项目目录&#xff0c;可以看到一个默认生成的项目目录结构 下图是目录结构&#xff1a; 详细介绍.vscode&#xff1a;存放VS Code编辑器的相关配置。 node_modules&#xff1a;存放项目的各种依赖和安装的插件。…

C# WPF上位机开发(通讯协议的编写)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 作为上位机&#xff0c;它很重要的一个部分就是需要和外面的设备进行数据沟通的。很多时候&#xff0c;也就是在这个沟通的过程当中&#xff0c;上…

极狐GitLab 与 Flux 集成实现 GitOps

目录 flux 和 GitOps 极狐GitLab 与 flux 的集成 flux 命令行安装 极狐GitLab flux GitOps GitOps Demo 写在最后 flux 和 GitOps 众所周知&#xff0c;weaveworks 公司在 2017 年提出了 GitOps 这个概念&#xff0c;而 flux 是 weaveworks 开源的一款对 Kubernetes 上的…

【总结】机器学习中的15种分类算法

目录 一、机器学习中的分类算法 1.1 基础分类算法 1.2 集成分类算法 1.3 其它分类算法&#xff1a; 二、各种机器学习分类算法的优缺点 分类算法也称为模式识别&#xff0c;是一种机器学习算法&#xff0c;其主要目的是从数据中发现规律并将数据分成不同的类别。分类算法通…

golang学习笔记——go流水线示例

range与数组、切片、集合 Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值&#xff0c;在集合中返回 key-value 对。 for 循环的 range 格式可以对 slice、map、数组、字…

计算机网络课程设计【Python实现】

一、网络聊天程序的设计与实现 1、实验目的 使用Socket编程&#xff0c;了解Socket通信的原理&#xff0c;会使用Socket进行简单的网络编程&#xff0c;并在此基础上编写聊天程序&#xff0c;运行服务器端和客户端&#xff0c;实现多个客户端通过服务器端进行通信。 2、总体设…

MongoDB 的复制(副本集)

本文主要介绍MongoDB的复制&#xff08;副本集&#xff09;。 目录 MongoDB的复制&#xff08;副本集&#xff09;特点搭建步骤注意事项 MongoDB的复制&#xff08;副本集&#xff09; MongoDB复制是一种提供数据冗余和高可用性的方法。复制是通过在多个节点上维护数据的副本来…

机器学习与人工智能:一场革命性的变革

机器学习与人工智能&#xff1a;一场革命性的变革 人工智能的概述什么是机器学习定义解释 数据集结构机器学习应用场景 人工智能的概述 1956年8月&#xff0c;在美国汉诺斯小镇宁静的达特茅斯学院中&#xff0c;约翰麦卡锡&#xff08;John McCarthy&#xff09;、马文闵斯基&…

科学小论文

赵州桥&#xff0c;是一座右拱桥&#xff0c;它座落于河北省石家庄市赵县城南液河之上。 赵州桥因赵县古称赵州而得名&#xff0c;当地人称之为大石桥&#xff0c;以区别于城西门外的永通桥&#xff0c;也称小石桥。 赵州桥始建于隋代&#xff0c;由匠师李春设计建造&#xff…

第一百九十九回 如何获取设备信息

文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 我们在上一章回中介绍了包管理相关的内容&#xff0c;本章回中将介绍如何使用url_launcher包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里介绍url_launcher包主要用来打开…

万户 ezOFFICE 文件上传漏洞复现

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…

HarmonyOS鸿蒙应用开发——HTTP网络访问与封装

文章目录 基本使用封装参考 基本使用 鸿蒙应用发起HTTP请求的基本使用&#xff0c;如下&#xff1a; 导入http模块创建httpRequest对象发起http请求&#xff0c;并处理响应结果 第一、导入http模块&#xff1a; import http from ohos.net.http第二、创建httpRequest对象&a…

SLAM教程:ROS学习

玩SLAM一定会遇到ROS,你可以看看稚晖君里的机器人操作系统,许多控制机器的软件代码很大程度都是基于ROS,多传感融合也是基于ROS,在GitHub上几乎大部分的多传感融合以及机器人操作代码框架都是基于ROS。ROS 的主要目标是为机器人研究和开发提供代码复用的支持。ROS是一个分布…

三翼鸟2023:需求中破局,进化中蝶变

当打造高质量生活的全民愿景以试卷的形式&#xff0c;打开在眼前&#xff0c;该如何作答&#xff1f;相信这是每个与“家”这个词息息相关的企业&#xff0c;最难给出肯定回答的难题。 科技、硬件擅长的企业&#xff0c;往往会选择以高科技为笔&#xff0c;画一幅智能家居生活…

【Matlab算法】多维函数求解的基本概念

多维函数求解的基本概念 多维函数最优化问题最优化算法最优化问题的类型最优化算法的分类常用的多维函数求解方法结语 多维函数 多维函数是指定义在 R n \mathbb{R}^n Rn 上的函数&#xff0c;其中 n n n 是函数的维数。例如&#xff0c; f ( x , y ) x 2 y 2 f(x, y) x^…