mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-14 16:07:52 +00:00
146 lines
14 KiB
Plaintext
146 lines
14 KiB
Plaintext
---
|
||
title: "Java 与 Kotlin"
|
||
description: "OpenIDEA 如何借助 JDT LS、Kotlin LSP、Maven 和 Gradle 为 Java 与 Kotlin 项目提供代码智能、构建、运行、测试和调试。"
|
||
---
|
||
|
||
Java 的代码智能由 Eclipse JDT Language Server(jdtls)提供,OpenIDEA 还为它加载了一组随应用发布的扩展 bundle;Kotlin 使用 JetBrains 的 Kotlin LSP。Maven 和 Gradle 项目会自动导入,两种语言的运行、测试和调试都走同一套运行配置。与其他语言的对比见[语言支持总览](/zh/languages/index)。
|
||
|
||
## 语言服务器
|
||
|
||
| 语言 | 服务器 | 备选 | 调试器 |
|
||
| ------------------- | -------------------------------------- | -------------------------------------------------------- | ------------------------------------- |
|
||
| Java | Eclipse JDT Language Server(`jdtls`) | `kmp-lsp` | Microsoft java-debug,加载在 jdtls 内 |
|
||
| Kotlin | Kotlin LSP(JetBrains,`kotlin-lsp`) | Kotlin Language Server(fwcd,`kotlin-language-server`) | Kotlin Debug Adapter(fwcd) |
|
||
| Groovy、Gradle 脚本 | `groovy-language-server`(需自行提供) | | |
|
||
| JSP | 无(仅语法高亮) | | |
|
||
|
||
备选服务器只在排在它前面的服务器未安装时才会启动。想手动指定,打开 **设置 › 语言和框架 › 语言服务器**,选中其中一个服务器,在 **Java 语言服务器**(或 Kotlin 语言服务器)里选择:**自动** 使用第一个可用的,**无** 关闭代码智能。这个选择可以全局生效,也可以只对当前项目生效。
|
||
|
||
`kmp-lsp` 不运行 JVM,提供基于语法的 Java 代码智能,没有 JDT 的编译分析、Lombok 支持和 JDT 的重构。构建和运行 Java “应用程序”配置、类路径发现以及 Java 调试器都需要 jdtls。
|
||
|
||
### 随 IDE 提供的部分
|
||
|
||
在原版 jdtls 之上,OpenIDEA 会加载仓库 [`java/`](https://github.com/l0ng-ai/openidea/tree/main/java) 目录里的扩展 bundle:
|
||
|
||
- **java-usages**:查找用法能区分读和写;对字段,还会一并找出它的 getter、setter 和 builder(包括 Lombok 生成的)。查找用法默认只搜项目源码(**项目文件**),选择 **项目和库** 时才会搜索依赖 jar。
|
||
- **Spring 配置导航**:见 [Spring](#spring)。
|
||
- **kotlin-bridge**:在 Java 与 Kotlin 混合的 Maven 项目里,让 Java 代码能看到 Kotlin 类。见下文“Maven 项目中的 Kotlin”。
|
||
- **Lombok**:应用内置一个打过补丁的 Lombok agent(1.18.48,修复了在当前 JDT LS 上的问题),无需下载。
|
||
|
||
没有源码的库类会以反编译后的 `jdt://` 文档打开。依赖有源码包时,jdtls 会下载 Maven 和 Eclipse 源码。
|
||
|
||
## 环境配置
|
||
|
||
### 安装服务器
|
||
|
||
打开 Java 或 Kotlin 文件时,如果对应的服务器缺失,会弹出通知并提供 **安装** 按钮。也可以在 **设置 › 语言和框架 › 语言服务器** 里安装、重新安装或卸载每个工具。所有工具都装进 IDE 自己的工具目录,不需要管理员权限:
|
||
|
||
| 工具 | 来源 |
|
||
| ----------------------------------- | ---------------------------------------------------------- |
|
||
| Eclipse JDT Language Server | download.eclipse.org 上的最新 milestone |
|
||
| Java 调试器(Microsoft java-debug) | Open VSX 上的 `vscjava.vscode-java-debug` 扩展 |
|
||
| Lombok(jdtls agent) | 随应用内置 |
|
||
| Kotlin LSP(JetBrains) | `Kotlin/kotlin-lsp` 的 GitHub release |
|
||
| Kotlin Language Server(fwcd) | `fwcd/kotlin-language-server` 的 GitHub release,需要 Java |
|
||
| Kotlin Debug Adapter | `fwcd/kotlin-debug-adapter` 的 GitHub release,需要 Java |
|
||
| kmp-lsp | `Hessesian/kmp-lsp` 的 GitHub release |
|
||
|
||
`PATH` 上已有的 `jdtls`(Homebrew、Scoop 或 release 压缩包)也能直接用。OpenIDEA 直接在 JVM 上启动它,不经过它自带的 Python 启动脚本,所以不需要装 Python。没装 java-debug 就开始调试时,IDE 会提示安装,并带着这个 bundle 重启 jdtls。
|
||
|
||
Groovy 没有安装程序:需要自行构建 [groovy-language-server](https://github.com/GroovyLanguageServer/groovy-language-server),以 `groovy-language-server` 的名字放到 `PATH` 上,或在 **语言服务器** 页面里指定可执行文件。
|
||
|
||
### JDK 检测
|
||
|
||
OpenIDEA 会在这些位置查找已安装的 JDK:`JAVA_HOME`、`PATH` 上的 `java`、`/Library/Java/JavaVirtualMachines`(系统级和用户级)、`/usr/lib/jvm`、Homebrew、SDKMAN、mise、asdf、`~/.jdks`,以及 Windows 上 `Program Files` 下常见的厂商目录。IDE 自己下载的 JDK 也会被找到。JDK 列表旁的 **重新检测** 可以重新扫描。
|
||
|
||
**设置 › 语言和框架 › Java** 里有两项 JDK 设置:
|
||
|
||
- **项目 JDK › SDK**:用于编译和运行项目。它是 jdtls 的默认运行时、运行/调试使用的 JDK,也是 Maven 和 Gradle 的 `JAVA_HOME`。选 **自动** 时,每个模块使用与其目标 Java 版本匹配的已安装 JDK。
|
||
- **语言服务器 › JDK**:只用来运行 jdtls,因此 Java 8 或 17 的项目也能用上新版 jdtls。选 **自动** 时,项目 JDK 版本够新就用它,否则用第一个满足要求的已安装 JDK;一个都没有时,会自动下载 Eclipse Temurin 到单独的语言服务器运行时目录。
|
||
|
||
jdtls 需要 JDK 21 或更高版本,部分 jdtls 版本要求更高,OpenIDEA 会从已安装的 jdtls 中读取实际要求。检测到的每个 JDK 还会作为运行时(`JavaSE-17`、`JavaSE-21`……)注册给 jdtls,所以目标是 Java 17 的模块会针对 JDK 17 编译,而不是针对运行 jdtls 的那个 JDK。
|
||
|
||
**语言级别** 在构建文件没有指定时决定 Java 源码和字节码级别。每个 JDK 列表里都有 **下载 JDK…**,可以选择版本,把 Eclipse Temurin 下载到 IDE 的 JDK 目录。当 jdtls、某个运行配置或 Maven/Gradle 同步找不到足够新的 JDK 时,也会提示同样的下载。
|
||
|
||
Kotlin Language Server(fwcd)最高只能在 Java 21 上运行。如果 `JAVA_HOME` 指向更新的 JDK,IDE 会改用已安装 JDK 中符合要求的最新版本来启动它。
|
||
|
||
### 内存与 JVM 选项
|
||
|
||
每个项目窗口各自启动一个 jdtls,有独立的工作区和索引。jdtls 默认使用以下 JVM 选项:
|
||
|
||
```text
|
||
-XX:+UseG1GC -XX:G1PeriodicGCInterval=60000 -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=30 -Xmx2G -Xms100m
|
||
```
|
||
|
||
G1 加上周期性回收,可以在导入或构建结束后把内存还给系统。要调整上限,在 **设置 › 语言和框架 › Java › 语言服务器 › JVM 选项** 中填写,例如 `-Xmx1g` 或 `-Xmx4g`。你设置的选项会替换同一项的默认值;指定其他回收器(如 `-XX:+UseZGC`)时,默认的回收器相关选项会全部去掉。该设置可以全局配置,也可以按项目配置。
|
||
|
||
**在构建间共享 JDT LS** 让一个本地项目窗口里所有关联的构建共用一个 jdtls,而不是每个构建一个。不同项目窗口之间仍然是各自独立的进程。
|
||
|
||
jdtls 的工作区保存在 IDE 的数据目录(`lsp/jdtls/`)中,不在项目里;jdtls 也不会往项目里写 `.project`、`.classpath` 或 `.settings`。见[数据目录与日志](/zh/reference/data-directories)。
|
||
|
||
### Lombok
|
||
|
||
项目用到 Lombok 时(在构建文件、继承的父 POM 或 Gradle 构建中声明,或源码里有相关 import),OpenIDEA 会给 jdtls 加上 Lombok agent。默认使用 **语言服务器** 页面里的那个,也就是内置的版本;没有时会退回到 Maven 或 Gradle 缓存里最新的 Lombok。你在 **JVM 选项** 里自己写的 `-javaagent` 优先。项目自身的 Lombok 依赖不会被改动。
|
||
|
||
## 构建工具
|
||
|
||
jdtls 会自动导入 Maven 和 Gradle 项目(包括 Gradle wrapper)。没有构建文件的目录会作为普通 Java 项目打开,`lib/` 下的 jar 会加入类路径。OpenIDEA 还提供 **Maven** 和 **Gradle** 工具窗口,用来执行目标和任务、重新加载、切换 profile 以及分析依赖。相关设置在 **设置 › 构建、执行、部署 › Maven** 和 **Gradle**:
|
||
|
||
- Maven:**JRE**、**Maven 主路径**(默认用项目的 `mvnw`,没有则用 `PATH` 上的 `mvn`)、**用户设置文件**、**Toolchains 文件**、**本地仓库**、**活动 profiles**、**线程数** 和 **使用 Maven Daemon (mvnd)**。在 Maven 工具窗口里选的 profile 也会传给 jdtls,编辑器看到的依赖与该 profile 一致。
|
||
- Gradle:**构建和运行使用**(Gradle 或 OpenIDEA)、**Gradle 使用的 JVM**、**分发**(Gradle 包装器或本地安装)、**Gradle 主路径** 和 **Gradle 用户主目录**。
|
||
|
||
IDE 会把代理设置传给 jdtls,所以在代理环境下也能解析依赖。工具窗口的用法见[构建工具](/zh/guide/build-tools)。
|
||
|
||
### Maven 项目中的 Kotlin
|
||
|
||
在含 Kotlin 源码的 Maven 项目里,每次保存后 OpenIDEA 会在后台用项目自己的 Maven 配置构建 Kotlin 代码,输出到一个私有目录,再把编译好的 Kotlin 类作为库交给 jdtls。这样同一模块或其他模块的 Java 代码就能调用 Kotlin 代码。这次构建的错误会以 `kotlin-bridge` 的名义出现在 **问题** 中;在下一次构建成功之前,继续使用上一次成功的结果。这个桥接只覆盖编译后的 Kotlin API,从 Java 跳转到 Kotlin 源码、分析未保存的 Kotlin 修改以及跨语言重构都不在其中。
|
||
|
||
## 运行与测试
|
||
|
||
| 对象 | 运行方式 |
|
||
| ----------------------------- | -------------------------------------------------------------------------------- |
|
||
| `main` 方法 | **应用程序** 配置,使用模块的运行时或测试类路径;支持 Java 25 的实例 `main` 方法 |
|
||
| `@SpringBootApplication` 类 | **Spring Boot** 配置,可设置活动 profile 和更新操作 |
|
||
| 可执行 jar | **JAR 应用程序** 配置 |
|
||
| WAR | **Tomcat 服务器** 配置,运行在本地 Tomcat 安装上(IDE 不会往安装目录里写东西) |
|
||
| JUnit 4、JUnit 5、TestNG 测试 | Maven(Surefire `-Dtest=…`)或 Gradle(`--tests …`)测试配置 |
|
||
|
||
main 方法、测试类和测试方法旁的边栏图标会创建这些配置;Maven 和 Gradle 的运行配置会从构建文件中自动检测。对 Gradle 项目,**构建和运行使用** 决定“应用程序”是作为 Gradle 的 `JavaExec` 任务运行(默认),还是由 OpenIDEA 用 jdtls 给出的类路径直接启动。
|
||
|
||
测试结果从 Maven 和 Gradle 生成的 JUnit XML 报告中读取,通过的测试也会列出;测试树支持只重跑失败的测试。Gradle 运行配置的 VM 选项会作用到 Gradle fork 出来的 JVM(`run`、`bootRun`、`test`)。类路径超出命令行长度限制时(Windows 上常见),会改用参数文件或只含 manifest 的 jar。
|
||
|
||
另见[运行配置](/zh/guide/run)和[测试](/zh/guide/testing)。
|
||
|
||
## 调试
|
||
|
||
Java 调试使用 jdtls 内的 Microsoft java-debug,Kotlin 调试使用 Kotlin Debug Adapter。可以调试:
|
||
|
||
- “应用程序”、Spring Boot、“JAR 应用程序”和“Tomcat 服务器”配置。
|
||
- 会启动 JVM 的 Maven 和 Gradle 配置(测试、`spring-boot:run`、`bootRun`、`run`):IDE 会加上 JDWP agent,等 JVM 就绪后自动附加,输出和测试树仍留在运行工具窗口里。
|
||
- 在别处启动的进程:使用 **远程 JVM 调试** 配置。
|
||
|
||
**运行 › 调试操作 › 重新加载已更改的类**(HotSwap)会编译你的修改并加载到正在运行的会话中。Spring Boot 和 Tomcat 配置还支持 **运行 › 更新应用**(`⌘F10` / `Ctrl+F10`),行为由 **执行“更新”操作时** 选项决定。
|
||
|
||
另见[调试](/zh/guide/debugging)。
|
||
|
||
## 框架支持
|
||
|
||
### Spring
|
||
|
||
- **Spring Boot 运行配置**:根据 `@SpringBootApplication` 类创建,默认显示在 **服务** 工具窗口中。
|
||
- **配置导航**:在 `application.yml` 或 `.properties` 的键上转到定义,会打开绑定到它的 Java 成员(`@ConfigurationProperties`、`@Value`、`Environment.getProperty`);反过来,从 Java、YAML、properties 或 Spring XML 里的 `${…}` 占位符也能跳到配置键。依赖中 `spring-configuration-metadata.json` 描述的键会跳到对应的源类。对配置键执行 **查找用法**,会同时列出配置声明和 Java 中的使用处。
|
||
- **Spring Web 端点**:Java 和 Kotlin 控制器中的请求映射旁有边栏图标,还有 **在 HTTP 客户端中生成请求** 和 **为控制器生成请求** 两个操作,会把请求写进一个临时 `.http` 文件。随处搜索的 **全部** 标签页可以按请求路径搜索。见 [HTTP Client](/zh/guide/http-client)。
|
||
- **Facet**:在 **项目结构**(`⌘;` / `Ctrl+Alt+Shift+S`)里记录模块使用的框架(Web、Spring、JPA)。添加 Web Facet 还会把其中的 `WEB-INF/lib/*.jar` 加入 jdtls 的类路径。
|
||
|
||
### MyBatis
|
||
|
||
MyBatis mapper 接口与 XML 语句之间的跳转由 MyBatis Navigator 插件([`plugins/official/mybatis`](https://github.com/l0ng-ai/openidea/tree/main/plugins/official/mybatis))提供,不属于 IDE 本体。
|
||
|
||
## 已知限制
|
||
|
||
- 每个项目窗口运行一个 jdtls,同时打开多个大项目时内存会叠加。可以在 **JVM 选项** 中调低 `-Xmx`,或关闭暂时不用的窗口。**在构建间共享 JDT LS** 只在单个窗口内有效。
|
||
- 没有 jdtls 时(例如只用 `kmp-lsp`),“应用程序”配置、依赖类路径的功能和 Java 调试都不可用。
|
||
- Java 测试通过 Maven 或 Gradle 运行,两者都没有的项目没有测试运行器。
|
||
- Kotlin 桥接只支持 Maven,只把编译后的 Kotlin 类暴露给 Java,不提供从 Java 到 Kotlin 源码的跳转或重构。
|
||
- Groovy 需要自行构建 `groovy-language-server`,JSP 只有语法高亮。
|