如何将Scala代码打包为可执行jar在仅装Java的机器上获取本机IP
问题原因澄清
你之前使用javap命令得到错误结果是因为javap是Java反编译工具,仅用于查看类文件结构,并非执行Java类的命令,执行类需要使用java命令。
另外Scala编译生成的class文件依赖Scala标准库,纯Java环境默认没有该依赖,因此需要将所有依赖打包进同一个fat jar,才能在无Scala环境的机器上直接运行。
打包方案
方案1:手动打包(无需构建工具)
- 编译Scala代码得到class文件:
scalac HostName.scala
- 找到本地Scala环境的标准库jar包,路径一般为Scala安装目录下的
lib/scala-library.jar,可通过以下命令查找:
find $SCALA_HOME -name "scala-library.jar"
- 解压Scala标准库到当前目录:
jar xf /path/to/scala-library.jar
- 编写manifest文件
MANIFEST.MF,指定程序入口主类,注意文件末尾需要留空行:
Main-Class: HostName
- 将所有文件打包为可执行jar:
jar cvfm HostIP.jar MANIFEST.MF *.class org/ javax/ java/
方案2:sbt打包(推荐,不易出错)
- 按照以下结构创建sbt项目:
hostip/ ├── build.sbt ├── project │ └── plugins.sbt └── src └── main └── scala └── HostName.scala
- 编写
build.sbt配置:
name := "HostIP" version := "1.0" // 替换为你本地使用的Scala版本 scalaVersion := "2.13.12" // 打包冲突处理规则 assembly / assemblyMergeStrategy := { case PathList("META-INF", _*) => MergeStrategy.discard case x => MergeStrategy.first } // 指定主类 assembly / mainClass := Some("HostName")
- 编写
project/plugins.sbt引入fat jar打包插件:
// 替换为匹配你sbt版本的插件版本 addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.2.0")
- 执行打包命令:
sbt assembly
打包完成后可在target/scala-<Scala版本号>/目录下得到带有所有依赖的可执行jar包。
运行方法
将打包好的HostIP.jar传到仅安装Java的机器上,直接执行以下命令即可得到IP:
java -jar HostIP.jar
在shell中获取输出的写法:
OUT=$(java -jar HostIP.jar)
代码优化提示
原代码使用InetAddress.getLocalHost.getHostAddress在部分Linux环境下可能会得到127.0.0.1,原因是/etc/hosts中默认将主机名映射到回环地址,可使用以下优化代码遍历网卡取非回环IPv4地址:
import java.net._ import scala.jdk.CollectionConverters._ object HostName { def main(args: Array[String]): Unit = { val validIps = NetworkInterface.getNetworkInterfaces.asScala .filter(ni => ni.isUp && !ni.isLoopback && !ni.isVirtual) .flatMap(_.getInetAddresses.asScala) .filter(addr => addr.isInstanceOf[Inet4Address] && !addr.isLoopbackAddress) .map(_.getHostAddress) .toList // 输出第一个有效IP,可按需调整为输出所有IP println(validIps.headOption.getOrElse("127.0.0.1")) } }
内容的提问来源于stack exchange,提问作者Aviral Srivastava
相关产品推荐
相关产品推荐

