Java 11官方统一下载与新特性详解
简介:Java 11是由Oracle发布的Java开发工具集主要版本,属于长期支持(LTS)版本,具有良好的兼容性、安全性及稳定性。该版本在Java 8基础上引入了多项新特性,如HTTP客户端模块、动态语言支持、JVM Attach API改进、JLink和JPackage工具等。文章强调通过官方渠道统一下载的重要性,并详细介绍了安装配置流程与开发实践,适合企业级开发者和项目维护人员使用。 
1. Java 11版本特性概述
Java 11 是 Oracle 官方发布的长期支持版本(LTS),自 2018 年发布以来,因其稳定性与企业级支持周期,广泛应用于生产环境。相较于 Java 8,Java 11 在语言语法、标准库、JVM 及工具链等方面均有显著增强。
在语法层面,Java 11 引入了 局部变量类型推断(var) ,简化了局部变量声明,提升了代码可读性。同时,支持 单文件源码直接运行( java MyClass.java ) ,省去编译步骤,提升脚本化开发效率。
API 方面,新增了如 HTTP Client API 、 字符串增强方法(如 isBlank() , lines() , repeat() ) ,以及文件操作的便捷方法( readString() , writeString() ),极大地提升了开发效率。
JVM 层面则引入了 低延迟垃圾回收器(ZGC)的实验性支持 ,为大型堆内存应用提供更低的 GC 停顿时间。
工具链方面, jlink 工具进一步完善,支持构建自定义最小化 JRE,适应容器化部署需求。
综上,Java 11 在保持向后兼容的同时,通过一系列现代化改进,为开发者提供了更高效、更灵活的编程体验,是迈向现代化 Java 开发的重要里程碑。
2. HTTP客户端API(java.net.http)使用
Java 11引入了标准的HTTP客户端API( java.net.http 包),这一新特性为Java开发者提供了一种现代化、简洁且功能丰富的网络通信方式。该API支持同步和异步请求,适用于GET、POST等多种HTTP方法,并具备SSL/TLS加密、重定向控制和Cookie管理等高级功能。本章将深入讲解 java.net.http 包的使用方式,帮助开发者掌握其核心组件和实际应用场景。
2.1 HTTP客户端API基本结构
Java 11的HTTP客户端API主要由三个核心类构成: HttpClient 、 HttpRequest 和 HttpResponse 。它们分别负责客户端配置、请求构建和响应处理。
2.1.1 HttpRequest与HttpResponse对象
HttpRequest 对象用于定义发送到服务器的HTTP请求,包括URL、方法类型、头部信息和请求体等内容。 HttpResponse 则用于封装服务器返回的响应数据。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpRequestExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.header("Content-Type", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
}
}
代码逐行解析:
HttpClient client = HttpClient.newHttpClient();:创建一个默认配置的HTTP客户端实例。HttpRequest.newBuilder():开始构建一个HTTP请求。.uri(...):设置请求的目标URI。.header(...):添加请求头信息。.GET():指定请求方法为GET。.build():构建请求对象。client.send(...):发送请求并获取响应。HttpResponse.BodyHandlers.ofString():将响应体转换为字符串格式。response.statusCode()和response.body():获取响应状态码和响应内容。
参数说明:
-uri:表示请求的目标地址。
-header:用于设置请求头,常用于身份验证或内容类型指定。
-GET():表示使用GET方法,也可以使用POST(...)等其他方法。
-BodyHandlers.ofString():用于将响应体转换为字符串类型,也可以使用ofFile(...)保存为文件。
2.1.2 HttpClient的创建与配置
HttpClient 是整个HTTP客户端API的核心,用于发送请求和管理连接。它支持自定义配置,如设置版本、代理、SSL上下文等。
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class HttpClientConfigExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.proxy(ProxySelector.of(new URI("http://myproxy:8080")))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
}
}
代码解析:
.version(HttpClient.Version.HTTP_2):设置HTTP版本为HTTP/2。.connectTimeout(...):设置连接超时时间为10秒。.proxy(...):设置代理服务器地址。.build():完成客户端构建。
参数说明:
-version:指定HTTP协议版本,如HTTP/1.1或HTTP/2。
-connectTimeout:连接超时时间,避免长时间阻塞。
-proxy:代理服务器配置,适用于需要通过代理访问网络的场景。
graph TD
A[HttpClient Builder] --> B[设置HTTP版本]
A --> C[设置连接超时]
A --> D[设置代理]
B & C & D --> E[构建HttpClient实例]
E --> F[发送HttpRequest]
F --> G{判断请求类型}
G -->|同步| H[获取HttpResponse]
G -->|异步| I[返回CompletableFuture]
2.2 同步与异步请求处理
Java 11的HTTP客户端API支持同步和异步两种请求处理方式,开发者可以根据业务需求灵活选择。
2.2.1 同步GET/POST请求实现
同步请求通过 HttpClient.send() 方法发送,适用于需要立即获取响应结果的场景。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class SyncGetExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());
}
}
POST请求示例:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest.BodyPublishers;
public class SyncPostExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
String json = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());
}
}
参数说明:
-BodyPublishers.ofString(json):构造POST请求的请求体,支持字符串、文件等多种形式。
-header("Content-Type", "application/json"):设置内容类型为JSON。
2.2.2 异步请求与CompletableFuture结合使用
异步请求通过 HttpClient.sendAsync() 方法发送,返回一个 CompletableFuture<HttpResponse<String>> ,适用于高并发或非阻塞式处理。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class AsyncGetExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.GET()
.build();
CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
future.thenAccept(response -> {
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
});
System.out.println("Main thread continues execution...");
Thread.sleep(2000); // 等待异步任务完成
}
}
执行逻辑说明:
sendAsync(...):发送异步请求,立即返回CompletableFuture。thenAccept(...):在响应到达后执行回调操作。Thread.sleep(...):模拟主线程等待异步任务完成。
| 请求类型 | 方法 | 是否阻塞 | 适用场景 |
|---|---|---|---|
| 同步 | send() |
是 | 简单请求、需立即返回结果 |
| 异步 | sendAsync() |
否 | 高并发、非阻塞式处理 |
graph LR
A[HttpClient.send()] --> B[同步阻塞]
A --> C[返回HttpResponse]
D[HttpClient.sendAsync()] --> E[异步非阻塞]
D --> F[返回CompletableFuture]
F --> G[thenAccept处理结果]
2.3 高级功能与安全配置
除了基本的请求处理,Java 11的HTTP客户端API还支持SSL/TLS加密、Cookie管理和重定向控制等高级功能。
2.3.1 SSL/TLS加密连接配置
对于HTTPS请求,可以自定义SSL上下文以增强安全性。
import javax.net.ssl.SSLContext;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class SslClientExample {
public static void main(String[] args) throws Exception {
SSLContext sslContext = SSLContext.getDefault();
HttpClient client = HttpClient.newBuilder()
.sslContext(sslContext)
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://self-signed.badssl.com/"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Body: " + response.body());
}
}
参数说明:
sslContext(...):设置自定义的SSL上下文,用于启用特定的加密协议或信任管理器。
2.3.2 Cookie管理与重定向控制
HTTP客户端API支持Cookie管理和重定向策略控制。
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class CookieRedirectExample {
public static void main(String[] args) throws Exception {
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
HttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://example.com"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Cookies: " + cookieManager.getCookieStore().getCookies());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Body: " + response.body());
}
}
参数说明:
-followRedirects(...):设置重定向策略,如NORMAL、ALWAYS或NEVER。
-CookieManager:用于自动管理服务器返回的Cookie信息。
| 功能 | 配置方式 | 作用 |
|---|---|---|
| SSL/TLS | sslContext(...) |
启用加密通信 |
| Cookie管理 | CookieManager |
自动存储和发送Cookie |
| 重定向控制 | followRedirects(...) |
控制是否跟随服务器重定向 |
graph TD
A[HttpClient配置] --> B[SSL Context设置]
A --> C[Cookie管理器设置]
A --> D[重定向策略设置]
B & C & D --> E[构建客户端]
E --> F[发送HTTPS请求]
F --> G{是否需要Cookie}
G -->|是| H[自动附加Cookie]
G -->|否| I[无Cookie发送]
3. JVM Attach API安全附加机制
JVM Attach API是Java平台提供的一种机制,允许外部进程(如诊断工具、监控系统、代码分析器等)动态附加(Attach)到一个正在运行的JVM实例中,进而执行诸如加载代理(Agent)、获取JVM状态信息等操作。Java 11在该机制的安全性方面进行了多项增强,包括权限控制、身份验证机制和策略文件配置等,使得Attach API的使用更加安全可控,尤其适用于生产环境中的监控与诊断。
3.1 Attach API的核心类与接口
Attach API主要位于 com.sun.tools.attach 包中,是JDK附带的一个工具类库,不属于Java标准API,因此在某些JRE环境中可能不可用。本节将介绍其核心类与接口,并分析其工作原理。
3.1.1 com.sun.tools.attach包介绍
该包中定义了多个关键类和接口,用于实现JVM附加功能。主要类包括:
| 类/接口 | 作用说明 |
|---|---|
VirtualMachine |
核心接口,代表一个正在运行的JVM实例,提供附加、加载代理等操作 |
VirtualMachineDescriptor |
表示一个JVM实例的描述符,用于标识要附加的目标JVM |
AttachProvider |
提供附加机制的实现,不同JVM厂商可能提供不同的实现 |
AgentLoadException |
在加载代理失败时抛出异常 |
IOException |
附加过程中可能出现的I/O错误 |
这些类协同工作,使得外部进程能够连接到目标JVM,并执行如加载Java Agent、获取JVM状态等操作。
3.1.2 虚拟机附加流程分析
Attach API的执行流程主要包括以下几个步骤:
graph TD
A[查找目标JVM] --> B[获取VirtualMachineDescriptor]
B --> C[调用AttachProvider.attach()]
C --> D[建立附加连接]
D --> E{是否成功?}
E -->|是| F[加载Agent或执行操作]
E -->|否| G[抛出异常]
F --> H[完成附加操作]
示例代码:附加并加载Agent
import com.sun.tools.attach.*;
import java.io.IOException;
import java.util.List;
public class AttachExample {
public static void main(String[] args) {
try {
// 获取所有正在运行的JVM实例
List<VirtualMachineDescriptor> vms = VirtualMachine.list();
for (VirtualMachineDescriptor vmd : vms) {
// 选择目标JVM,假设我们附加第一个实例
if (vmd.displayName().contains("MyApp")) {
VirtualMachine vm = VirtualMachine.attach(vmd);
// 加载Agent(假设agent.jar位于指定路径)
vm.loadAgent("/path/to/agent.jar");
vm.detach(); // 断开连接
break;
}
}
} catch (AttachNotSupportedException | IOException | AgentLoadException e) {
e.printStackTrace();
}
}
}
代码逐行解读与参数说明:
- 第6行 :调用
VirtualMachine.list()方法获取当前机器上所有运行中的JVM实例描述符。 - 第9行 :通过
vmd.displayName()筛选出目标JVM,通常可以根据进程ID或应用名进行判断。 - 第11行 :使用
attach()方法连接目标JVM,建立附加连接。 - 第13行 :调用
loadAgent()加载指定路径的Java Agent,该Agent通常包含premain方法,用于在JVM启动后执行操作。 - 第14行 :调用
detach()方法断开与目标JVM的连接,释放资源。 - 异常处理 :
AttachNotSupportedException:表示当前平台不支持Attach机制。IOException:附加过程中发生I/O错误。AgentLoadException:加载Agent失败。
3.2 安全附加机制的改进
Java 11对JVM Attach API的安全机制进行了增强,主要包括权限控制、身份验证机制和安全策略文件的配置。这些改进有效防止了未经授权的进程对JVM的非法附加,增强了系统的安全性。
3.2.1 权限控制与身份验证机制
在Java 11中,JVM默认对附加操作进行了权限限制。只有具有相应权限的用户或进程才能附加到目标JVM。这主要通过以下机制实现:
- 基于操作系统用户权限的限制 :附加进程必须与目标JVM运行在相同的操作系统用户下,或具有足够权限的用户。
- JVM启动参数控制 :
-XX:+DisableAttachMechanism:禁用Attach机制,防止任何进程附加。-XX:+RestrictedVMStates:限制JVM在特定状态(如崩溃)下允许附加。- 使用Java安全管理器(SecurityManager) :如果启用了安全管理器,附加操作将受到更严格的权限控制。
示例:禁用Attach机制
java -XX:+DisableAttachMechanism -jar myapp.jar
该命令启动的JVM将不允许任何外部进程通过Attach API进行附加。
3.2.2 安全策略文件设置
Java 11允许通过策略文件(policy file)对Attach API的使用进行更细粒度的权限控制。策略文件通常位于JDK的 lib/security 目录下,可以通过 -Djava.security.policy 参数指定。
示例策略文件内容:
grant codeBase "file:/path/to/myagent.jar" {
permission com.sun.tools.attach.AttachPermission;
};
上述策略表示:仅允许 myagent.jar 这个Agent执行Attach操作,其他程序将被拒绝。
启用策略文件的启动命令:
java -Djava.security.manager -Djava.security.policy==/path/to/policyfile -jar myapp.jar
说明:
-Djava.security.manager:启用安全管理器。-Djava.security.policy==policyfile:指定策略文件,双等号表示不使用默认策略。AttachPermission:授予特定代码附加到JVM的权限。
3.3 Attach API的典型应用场景
Attach API在实际开发和运维中具有广泛的应用场景,主要包括动态加载代理和JVM监控诊断工具集成两大方向。
3.3.1 动态加载代理(Instrumentation)
Java Agent是一种特殊的类,可以在JVM启动后通过Attach API动态加载,实现对类的Instrumentation(插桩),用于性能监控、日志增强、热修复等功能。
示例:编写一个简单的Java Agent
import java.lang.instrument.Instrumentation;
public class SimpleAgent {
public static void premain(String args, Instrumentation inst) {
System.out.println("Agent loaded with args: " + args);
inst.addTransformer((loader, className, classBeingRedefined,
protectionDomain, classfileBuffer) -> {
// 实现类的转换逻辑
return modifiedBytecode; // 返回修改后的字节码
});
}
}
MANIFEST.MF配置:
Manifest-Version: 1.0
Premain-Class: SimpleAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
使用方式:
java -javaagent:simpleagent.jar -jar myapp.jar
或通过Attach API动态附加:
vm.loadAgent("simpleagent.jar", "myargs");
3.3.2 JVM监控与诊断工具集成
Attach API广泛用于各种JVM监控工具(如VisualVM、JConsole、JProfiler)和诊断工具(如jstack、jmap)中。这些工具通过附加到目标JVM,获取线程堆栈、内存快照、类加载信息等,帮助开发者进行性能分析和问题定位。
示例:使用jstack获取线程堆栈
jstack <pid>
该命令通过Attach API附加到指定PID的JVM进程,获取当前线程堆栈信息。
示例:Attach API实现类似jstack的功能
VirtualMachine vm = VirtualMachine.attach(pid);
vm.loadAgent("path/to/diagagent.jar", "threadDump");
其中, diagagent.jar 内部调用 ThreadMXBean 获取线程信息并输出。
小结(非总结性语言,仅作为内容引导)
通过本章的学习,我们深入了解了JVM Attach API的核心类与接口,掌握了其附加流程与典型使用方式,并重点分析了Java 11中在安全机制上的改进,包括权限控制、身份验证与策略文件配置。最后,我们探讨了Attach API在动态加载Agent和JVM监控工具中的典型应用场景,展示了其在实际开发和运维中的强大功能。
后续章节将继续探讨Java 11的安装配置、JLink构建自定义JRE、JFR性能监控等实用技术,帮助开发者全面掌握Java 11的高级特性与最佳实践。
4. Java 11安装配置步骤详解
正确安装与配置Java 11是开发环境搭建的首要任务。本章将从Java 11的获取方式、平台适配、环境变量配置、版本管理到开发工具集成进行全面解析。通过本章内容,开发者将掌握在不同操作系统下安装与配置Java 11的完整流程,并能熟练管理多个JDK版本共存的开发环境。
4.1 下载与安装方式
Java 11作为长期支持版本(LTS),官方提供了多个渠道进行下载与安装。本节将详细介绍推荐的下载源、安装包格式以及在不同平台上的安装方式。
4.1.1 官方与统一下载源推荐
Java 11的官方下载主要由Oracle和Adoptium(原AdoptOpenJDK)提供,两者均支持多平台安装包。
| 下载源 | 网站地址 | 支持平台 | 是否商业用途 |
|---|---|---|---|
| Oracle JDK | https://www.oracle.com/java/technologies/javase-jdk11-downloads.html | Windows/Linux/macOS | 是(需许可) |
| Adoptium(Eclipse Temurin) | https://adoptium.net/zh-CN/temurin/releases/?version=11 | 多平台支持 | 免费、开源 |
推荐使用Adoptium :因其完全开源、支持广泛平台、更新及时,并且可作为生产环境的免费替代方案。
4.1.2 Windows、Linux、macOS平台安装包说明
Windows
- 安装包类型 :
.msi或.zip - 建议使用
.msi安装包 :可自动配置环境变量。 - 手动解压方式 :适用于需要多版本管理或绿色部署的场景。
Linux(如Ubuntu、CentOS)
- 安装方式 :
- 使用包管理器安装(如
apt、yum) - 下载
.tar.gz解压安装
示例命令(基于Adoptium):
wget https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.20%2B8/OpenJDK11U-jdk_x64_linux_hotspot_11.0.20_8.tar.gz
tar -xzf OpenJDK11U-jdk_x64_linux_hotspot_11.0.20_8.tar.gz -C /opt
macOS
- 安装方式 :
.pkg安装包:双击安装即可.tar.gz:手动解压至/Library/Java/JavaVirtualMachines/
tar -xzf OpenJDK11U-jdk_x64_mac_hotspot_11.0.20_8.tar.gz
sudo mv jdk-11.jdk /Library/Java/JavaVirtualMachines/
提示 :macOS系统中可通过
/usr/libexec/java_home查看已安装的JDK路径。
安装方式流程图(mermaid)
graph TD
A[选择下载源] --> B{平台类型}
B -->|Windows| C[下载.msi或.zip]
B -->|Linux| D[下载.tar.gz或使用apt/yum]
B -->|macOS| E[下载.pkg或.tar.gz]
C --> F[运行安装程序或解压]
D --> G[解压到/opt或使用包管理器]
E --> H[双击.pkg或手动移动到Java目录]
4.2 环境变量配置
Java的运行依赖于正确的环境变量配置,尤其是 JAVA_HOME 和 PATH 的设置。此外,在多版本JDK共存的开发环境中,合理配置是关键。
4.2.1 JAVA_HOME与PATH设置
设置步骤(以Linux为例):
- 查看Java安装路径 :
ls /opt | grep jdk
假设路径为 /opt/jdk-11.0.20+8
- 编辑系统环境变量文件 :
sudo nano /etc/profile.d/java.sh
- 添加如下内容 :
export JAVA_HOME=/opt/jdk-11.0.20+8
export PATH=$JAVA_HOME/bin:$PATH
- 应用配置 :
source /etc/profile.d/java.sh
Windows系统配置:
- 打开“系统属性” -> “高级系统设置” -> “环境变量”
- 新建系统变量
JAVA_HOME,值为JDK安装路径(如C:\Program Files\Java\jdk-11.0.20) - 编辑
PATH,添加%JAVA_HOME%\bin
4.2.2 多版本JDK共存管理
在实际开发中,常常需要在多个JDK版本之间切换。以下是两种常见解决方案:
1. 使用 update-alternatives (Linux)
sudo update-alternatives --install /usr/bin/java java /opt/jdk-11.0.20+8/bin/java 1
sudo update-alternatives --config java
2. 使用 jEnv (跨平台)
安装 jEnv:
git clone https://github.com/jenv/jenv.git ~/.jenv
echo 'export PATH="$HOME/.jenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(jenv init -)"' >> ~/.bashrc
source ~/.bashrc
添加JDK:
jenv add /opt/jdk-11.0.20+8
查看已添加版本:
jenv versions
切换版本:
jenv global 11
多版本管理工具对比表
| 工具 | 支持平台 | 特点 |
|---|---|---|
| jEnv | Linux/macOS | 轻量、易用,支持版本切换 |
| SDKMAN! | Linux/macOS | 支持多语言,集成JDK管理 |
| Windows环境变量 | Windows | 手动配置,适合少量版本 |
| Jabba | 多平台 | Node.js风格版本管理,支持JDK |
4.3 验证安装与版本切换
安装完成后,必须验证Java版本是否正确加载,并能根据需求切换JDK版本。
4.3.1 java -version命令验证
运行以下命令验证Java是否安装成功:
java -version
输出示例:
openjdk version "11.0.20" 2023-04-18
OpenJDK Runtime Environment Adoptium-11.0.20+8 (build 11.0.20+8)
OpenJDK 64-Bit Server VM Adoptium-11.0.20+8 (build 11.0.20+8, mixed mode)
同时验证 javac :
javac -version
输出示例:
javac 11.0.20
4.3.2 使用jEnv或SDKMAN进行版本切换
使用 jEnv 切换版本:
jenv global 11
使用 SDKMAN 切换版本:
安装 SDKMAN:
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
查看可用版本:
sdk list java
安装特定版本:
sdk install java 11.0.20-tem
切换版本:
sdk use java 11.0.20-tem
注意 :SDKMAN支持多个语言环境管理,适合需要切换多种语言版本的开发者。
JDK版本切换流程图(mermaid)
graph TD
A[安装多个JDK版本] --> B{选择管理工具}
B -->|jEnv| C[配置JAVA_HOME与PATH]
B -->|SDKMAN| D[使用sdk use命令切换]
C --> E[执行jenv global <version>]
D --> F[验证版本: java -version]
4.4 开发工具集成
安装好Java 11后,还需将其集成到主流开发工具中,确保项目能够正确识别与使用JDK 11。
4.4.1 IntelliJ IDEA、Eclipse中配置JDK 11
IntelliJ IDEA:
- 打开设置:
File->Project Structure - 在
SDKs选项卡中点击+号 - 选择JDK安装目录(如
/opt/jdk-11.0.20+8) - 在
Project选项卡中选择新添加的JDK作为项目JDK
Eclipse:
- 打开偏好设置:
Window->Preferences - 选择
Java->Installed JREs - 点击
Add...,选择标准VM - 输入JRE名称,如
JDK 11 - 浏览选择JDK安装目录
- 勾选新添加的JRE作为默认
4.4.2 Maven与Gradle构建工具兼容性调整
Maven配置:
在 pom.xml 中指定Java版本:
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
若使用Maven Compiler Plugin,可配置如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
Gradle配置:
在 build.gradle 中添加:
sourceCompatibility = '11'
targetCompatibility = '11'
使用Gradle Wrapper时,确保 gradle.properties 中有:
org.gradle.java.home=/opt/jdk-11.0.20+8
IDE与构建工具配置流程图(mermaid)
graph TD
A[安装Java 11] --> B[配置IDE]
B -->|IntelliJ IDEA| C[设置Project SDK]
B -->|Eclipse| D[添加并设置Installed JRE]
A --> E[配置构建工具]
E -->|Maven| F[修改pom.xml]
E -->|Gradle| G[设置build.gradle]
本章从Java 11的获取、安装、环境变量配置、版本管理到开发工具集成进行了系统讲解。通过本章内容,开发者可以独立完成Java 11的安装与配置工作,并能够在多版本共存环境中灵活切换,为后续Java 11开发打下坚实基础。下一章我们将深入探讨JLink工具,学习如何构建自定义JRE运行环境。
5. JLink自定义JRE构建技术
Java 9 引入了 JLink 工具,用于构建轻量级、自定义的 Java 运行时环境(JRE)。Java 11 在此基础上进一步完善了该工具的功能,使其更适用于云原生和容器化部署场景。本章将深入探讨 JLink 的作用、构建流程以及与现代部署架构的集成方式。
5.1 JLink工具概述
JLink 是一个命令行工具,用于将 Java 模块系统中的特定模块组合成一个自定义的运行时镜像。与传统的完整 JRE 相比,自定义 JRE 仅包含应用实际需要的模块,大幅减少运行时体积,提升启动速度和资源利用率。
5.1.1 模块化系统与JRE裁剪原理
Java 9 开始引入的模块化系统(JPMS,Java Platform Module System)是 JLink 实现自定义 JRE 的基础。模块化将 Java SE API 划分为多个独立模块(如 java.base、java.net.http 等),每个模块封装了特定的功能。
JRE裁剪原理如下:
- 模块依赖分析 :JLink 会分析应用所需的模块及其依赖项。
- 模块打包 :将分析出的模块打包到一个自定义运行时镜像中。
- 运行时镜像生成 :最终生成一个包含所有必需模块的最小化 JRE。
通过这种方式,JLink 能够构建一个仅包含应用所需功能的运行时环境,避免引入不必要的类库和资源。
5.1.2 jlink命令的基本用法
jlink 是 JDK 提供的一个命令行工具,位于 $JAVA_HOME/bin 目录下。其基本语法如下:
jlink [options] --module-path modulepath --add-modules module1,module2,...
常用参数说明:
| 参数 | 描述 |
|---|---|
--module-path 或 -p |
指定模块路径,通常为 $JAVA_HOME/jmods |
--add-modules 或 -addmods |
指定要添加到自定义运行时中的模块 |
--output 或 -o |
指定输出目录,生成自定义 JRE 的位置 |
--strip-debug |
去除调试信息,减少镜像体积 |
--compress |
压缩资源文件,可选级别为 0-2 |
--no-header-files |
不包含 C 头文件 |
--no-man-pages |
不包含手册页 |
示例:构建一个仅包含 java.base 和 java.logging 模块的运行时镜像
jlink -p $JAVA_HOME/jmods \
-addmods java.base,java.logging \
-o custom-jre \
--strip-debug \
--compress=2 \
--no-header-files \
--no-man-pages
执行逻辑分析:
-p指定模块路径,这里是 JDK 的 jmods 目录。-addmods指定要添加的模块,这里是java.base和java.logging。-o表示输出路径,生成的自定义 JRE 将保存在custom-jre目录。--strip-debug移除调试信息,使镜像更小。--compress=2使用最高压缩级别压缩资源。--no-header-files和--no-man-pages去除不必要的文件。
构建结果:
执行完毕后, custom-jre 文件夹中将包含一个最小化的 JRE 环境,其结构如下:
custom-jre/
├── bin/
│ ├── java
│ └── keytool
├── conf/
├── legal/
├── lib/
└── release
这个运行时镜像可以在其他环境中独立运行,前提是该应用仅使用了 java.base 和 java.logging 模块。
5.2 自定义JRE构建实践
在实际项目中,我们需要根据应用依赖的模块进行精确构建,避免遗漏或冗余。本节将演示如何基于一个实际 Java 应用构建自定义 JRE,并验证其运行效果。
5.2.1 指定模块列表并生成运行时镜像
假设我们有一个简单的 Java 应用,使用了 java.base 、 java.logging 和 java.net.http 模块,其源码如下:
// Main.java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
}
}
构建步骤如下:
- 编译应用:
javac --module-path $JAVA_HOME/jmods -d out Main.java
- 运行 jlink 构建自定义 JRE:
jlink -p $JAVA_HOME/jmods \
-addmods java.base,java.logging,java.net.http \
-o custom-jre \
--strip-debug \
--compress=2 \
--no-header-files \
--no-man-pages
- 打包应用 JAR 文件:
jar -cfe app.jar Main -C out .
- 使用自定义 JRE 运行应用:
custom-jre/bin/java -jar app.jar
输出示例:
Status Code: 200
Response Body: {"userId":1,"id":1,"title":"..."}
5.2.2 构建结果验证与部署测试
为了确保自定义 JRE 能在目标环境中正常运行,我们需要进行以下验证步骤:
- 验证运行时镜像大小:
du -sh custom-jre
输出示例:
35M custom-jre
相比完整 JRE 几百 MB 的体积,35MB 的自定义运行时显然更适合容器化部署。
- 验证模块依赖是否完整:
使用 jdeps 工具分析应用的模块依赖:
jdeps -s --module-path $JAVA_HOME/jmods app.jar
输出示例:
app.jar -> java.base
app.jar -> java.net.http
app.jar -> java.logging
这说明我们构建时选择的模块是完整的,没有遗漏。
- 部署到 Docker 容器中测试:
我们可以将自定义 JRE 与应用打包成一个极简的 Docker 镜像:
FROM scratch
COPY custom-jre /custom-jre
COPY app.jar /app.jar
ENTRYPOINT ["/custom-jre/bin/java", "-jar", "/app.jar"]
构建并运行:
docker build -t custom-jre-app .
docker run custom-jre-app
该容器镜像的体积将小于 40MB,非常适合用于微服务或 Serverless 架构。
5.3 与容器化技术的结合
JLink 构建的自定义 JRE 在容器化部署中展现出显著优势。它不仅减少了镜像体积,还提升了启动速度和资源利用率,尤其适用于 Kubernetes、Docker Swarm 等编排平台。
5.3.1 Docker镜像优化
传统 Java 应用通常基于官方 OpenJDK 镜像(如 openjdk:11-jdk ),其体积通常在 400MB 左右。使用 JLink 构建的自定义运行时可以将镜像体积压缩至 40MB 以内,极大提升部署效率。
优化后的 Docker 构建流程如下:
- 在构建阶段使用完整 JDK 编译应用和构建自定义 JRE
- 在最终镜像中仅保留自定义 JRE 和应用 JAR 文件
# 构建阶段
FROM openjdk:11-jdk as builder
COPY . /src
WORKDIR /src
RUN javac -d out Main.java && \
jar -cfe app.jar Main -C out . && \
jlink -p $JAVA_HOME/jmods \
-addmods java.base,java.net.http,java.logging \
-o custom-jre \
--strip-debug \
--compress=2 \
--no-header-files \
--no-man-pages
# 最终运行镜像
FROM scratch
COPY --from=builder /src/custom-jre /custom-jre
COPY --from=builder /src/app.jar /app.jar
ENTRYPOINT ["/custom-jre/bin/java", "-jar", "/app.jar"]
构建并运行:
docker build -t tiny-java-app .
docker run tiny-java-app
该镜像的最终大小约为 38MB,几乎可以媲美 Go 语言构建的镜像。
5.3.2 与微服务架构的集成建议
在微服务架构中,服务实例通常需要快速启动、频繁部署和弹性伸缩。JLink 构建的自定义 JRE 在以下几个方面特别适合:
- 镜像体积小 :提升 CI/CD 流程效率,降低镜像拉取时间。
- 资源占用低 :适合运行在资源受限的环境中(如 Kubernetes Pod)。
- 快速启动 :由于模块数量少,JVM 启动更快,适合 Serverless 等按需启动的场景。
- 安全性高 :只包含必需模块,减少攻击面。
建议实践:
- 模块管理自动化 :结合构建工具(如 Maven、Gradle)自动生成模块依赖列表。
- 镜像构建流水线 :在 CI 流程中集成 JLink 构建步骤,实现自动化生成。
- 多版本兼容测试 :虽然 Java 11 支持大多数模块,但某些第三方库可能仍依赖 JDK 内部 API,需提前验证。
- 监控运行时行为 :使用 Java Flight Recorder(JFR)等工具监控自定义运行时中的性能和资源使用情况。
通过本章的学习,你已经掌握了如何使用 JLink 构建自定义 JRE,了解了模块化系统的原理,并掌握了其在容器化部署和微服务架构中的实际应用技巧。下一章我们将介绍 Java 11 中的性能监控利器 —— Java Flight Recorder(JFR),帮助你更深入地理解应用运行状态和性能瓶颈。
6. Java Flight Recorder性能监控
Java Flight Recorder(JFR)是Java 11中正式引入的内置性能监控工具,它提供了一种低开销、持续记录JVM及其运行应用程序行为的方式。JFR能够收集线程、GC、I/O、类加载、锁竞争、方法执行等多方面的运行时数据,为性能分析和故障诊断提供了强大的支持。在本章中,我们将深入探讨JFR的架构原理、使用方法,并结合Java Mission Control(JMC)进行可视化分析,帮助开发者掌握如何在生产环境中进行性能监控与调优。
6.1 JFR的基本概念与架构
JFR的设计初衷是为了在不影响应用性能的前提下,提供细粒度的运行时数据记录功能。它基于事件驱动模型,将JVM和应用的行为抽象为事件(Event),并通过高效的事件流机制进行记录。
6.1.1 事件类型与事件流机制
JFR定义了多种预定义的事件类型,涵盖JVM各个子系统的行为。例如:
| 事件类别 | 示例事件 | 描述 |
|---|---|---|
| GC | GC Start、GC Pause、GC Heap Summary | 记录垃圾回收的开始、暂停时间、堆内存状态等 |
| 线程 | Thread Start、Thread End、Thread Park | 线程生命周期和阻塞行为 |
| I/O | Socket Read、File Read、File Write | 文件和网络I/O操作 |
| 方法执行 | Method Sample、Method Profiling | 方法执行时间和调用堆栈 |
| 内存 | Object Allocation In New TLAB、Object Allocation Outside TLAB | 对象分配行为 |
JFR采用事件流机制(Event Streaming),事件被记录到内存缓冲区中,定期写入磁盘或通过JMX传输。这种设计保证了JFR的低开销(通常小于2%)和高扩展性。
6.1.2 飞行记录器的启动与管理
JFR可以在应用启动时自动启用,也可以在运行时动态启动。以下是两种常见方式:
启动JFR的命令行方式
java -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s,filename=myrecording.jfr MyApplication
-XX:+FlightRecorder:启用JFR。-XX:StartFlightRecording:指定录制参数。duration=60s:录制持续60秒。filename=myrecording.jfr:保存记录文件为myrecording.jfr。
使用JMX API动态控制JFR
import jdk.management.jfr.FlightRecorderMXBean;
import java.lang.management.ManagementFactory;
public class JFRControl {
public static void main(String[] args) throws Exception {
FlightRecorderMXBean bean = ManagementFactory.getPlatformMXBean(FlightRecorderMXBean.class);
String recording = bean.newRecording();
bean.start(recording); // 启动记录
Thread.sleep(30000); // 记录30秒
bean.stop(recording); // 停止记录
bean.dump(recording, "myrecording_runtime.jfr"); // 导出记录
bean.closeRecording(recording); // 关闭记录
}
}
代码逻辑分析:
- 获取FlightRecorderMXBean实例 :通过JMX接口获取JFR的管理接口。
- newRecording() :创建一个新的记录会话。
- start(recording) :开始记录。
- sleep(30000) :记录30秒的应用行为。
- stop(recording) :停止记录。
- dump(recording, “myrecording_runtime.jfr”) :将记录保存为
.jfr文件。 - closeRecording(recording) :释放资源。
6.2 使用JFR进行性能分析
JFR记录的数据可用于分析多个性能维度,包括垃圾回收效率、线程行为、I/O瓶颈等。我们以GC和线程监控为例,展示如何通过JFR定位性能问题。
6.2.1 启动JFR并记录运行数据
我们可以使用以下命令启动应用并记录GC行为:
java -XX:+FlightRecorder -XX:StartFlightRecording=duration=60s,name=test-gc,filename=gc_recording.jfr -jar myapp.jar
该命令将在应用启动后自动记录60秒的运行行为,并将GC事件写入 gc_recording.jfr 。
6.2.2 分析GC、线程、I/O等关键指标
GC事件分析示例
在JFR记录中,常见的GC事件包括:
sequenceDiagram
participant JFR
participant GC
participant Application
JFR->>GC: 注册GC事件监听器
GC->>JFR: 发送GC开始事件
GC->>Application: 执行GC
GC->>JFR: 发送GC结束事件
JFR->>Application: 汇总GC时间与内存变化
分析GC性能指标:
- GC Pause Time :每次GC的暂停时间。
- Heap Usage Before/After GC :GC前后堆内存使用情况。
- GC Frequency :GC发生的频率。
- Memory Allocation Rate :每秒对象分配率。
线程事件分析
JFR可以记录线程的创建、销毁、阻塞、等待等事件,帮助识别线程瓶颈:
jfr thread dump --file=recording.jfr
该命令可以查看所有线程的状态快照,用于排查死锁、线程池瓶颈等问题。
6.3 与Java Mission Control结合使用
Java Mission Control(JMC)是JDK附带的可视化分析工具,专门用于打开和分析JFR记录的 .jfr 文件。
6.3.1 JMC工具的安装与配置
JMC通常随JDK安装包一起发布,位于 $JAVA_HOME/bin/jmc 目录下。
启动JMC:
$JAVA_HOME/bin/jmc
JMC界面包含多个视图,如:
- Overview :展示JVM整体运行状态。
- Memory :分析堆内存使用和GC行为。
- Threads :显示线程状态、锁竞争情况。
- Code :方法执行时间、调用栈等。
6.3.2 可视化分析JFR记录文件
将上一节生成的 gc_recording.jfr 文件导入JMC后,可以直观查看:
- GC暂停时间分布图
- 堆内存使用趋势图
- 方法调用热点图(Hot Methods)
例如,在 Hot Methods 标签下可以看到执行时间最长的方法:
| 方法名 | 调用次数 | 平均执行时间(ms) | 总耗时占比 |
|---|---|---|---|
java.util.HashMap.put |
120000 | 0.05 | 23.5% |
java.lang.String.indexOf |
80000 | 0.03 | 15.2% |
这有助于识别热点代码并进行性能优化。
6.3.3 使用JFR进行生产环境诊断
在生产环境中,JFR可以通过以下方式部署:
java -XX:+FlightRecorder -XX:FlightRecorderOptions=settings=profile,disk=true,repository=/var/jfr -jar myapp.jar
settings=profile:使用高性能的profile配置。disk=true:启用磁盘记录。repository=/var/jfr:指定记录文件的存储路径。
在发生性能问题时,可以通过JMX API或JCMD动态触发记录:
jcmd <pid> JFR.start name=prod-recording duration=30s filename=/var/jfr/prod.jfr
6.3.4 高级配置与自定义事件
JFR支持自定义事件,开发者可以定义自己的业务事件进行记录。
自定义事件示例:
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Description;
@Label("My Custom Event")
@Description("This is a custom event for business logic monitoring.")
public class MyBusinessEvent extends Event {
@Label("Operation")
private final String operation;
@Label("Duration (ms)")
private final long duration;
public MyBusinessEvent(String operation, long duration) {
this.operation = operation;
this.duration = duration;
}
public static void main(String[] args) {
MyBusinessEvent event = new MyBusinessEvent("login", 123);
event.commit(); // 提交事件到JFR
}
}
代码解释:
@Label和@Description:用于定义事件字段的标签和描述,便于在JMC中识别。event.commit():提交事件,触发记录。
在JMC中,可以看到该事件出现在“Events”面板中,帮助开发者追踪业务逻辑的执行情况。
6.3.5 JFR性能影响与调优建议
尽管JFR的开销较低,但在高并发或低延迟场景中仍需谨慎使用:
| 场景 | 调优建议 |
|---|---|
| 高吞吐量系统 | 启用 settings=profile 模式,减少记录频率 |
| 实时性要求高 | 限制记录时长,使用异步写入 |
| 容器环境 | 将记录文件写入共享卷,便于集中分析 |
| 日志与JFR并行使用 | 避免同时记录大量日志,减少I/O竞争 |
通过本章的学习,读者应能够掌握Java Flight Recorder的基本原理、使用方式以及如何结合Java Mission Control进行性能分析与问题诊断。JFR是Java 11中非常实用的性能监控工具,合理使用可大幅提升系统可观测性和调优效率。
7. Java 11开发实践与性能优化技巧
Java 11作为企业级长期支持版本,在实际项目开发中被广泛采用。为了充分发挥其性能潜力,开发者需要结合项目实际情况,采取合理的开发实践与调优策略。本章将从开发常见问题、JVM调优、应用性能提升以及CI/CD流程优化等方面,系统性地讲解Java 11在项目中的最佳实践。
7.1 项目开发中的常见问题与解决方案
在Java 11项目开发过程中,开发者常常会遇到模块冲突、类加载异常以及JDK内部API使用限制等问题。这些问题需要从底层机制入手,才能高效定位与解决。
7.1.1 类加载与模块冲突处理
Java 9引入的模块系统(JPMS)在Java 11中得到进一步完善。模块化虽然提升了代码的封装性,但也带来了类加载器冲突、模块版本冲突等新问题。
典型问题示例:
Error: java.lang.LinkageError: loader constraint violation
这个错误通常发生在两个不同的模块加载了相同的类,导致JVM无法确定使用哪一个类版本。
解决方案:
- 使用
--add-exports或--add-opens参数显式控制模块导出与开放权限。 - 使用
jdeps工具分析模块依赖关系:
jdeps --module-path $JAVA_HOME/jmods --add-modules java.base your-app.jar
- 若使用Maven或Gradle构建工具,可引入插件如
maven-shade-plugin或shadow插件进行依赖重定位,避免类冲突。
7.1.2 JDK内部API的使用限制与替代方案
Java 11默认禁止使用JDK内部API(如 sun.misc.Unsafe ),尝试访问会抛出如下错误:
java.lang.IllegalAccessException: class com.example.MyClass cannot access a member of class sun.misc.Unsafe with modifiers "private static final"
替代方案:
- 使用
--add-exports或--add-opens允许访问内部API(不推荐长期使用):
--add-exports java.base/sun.misc=ALL-UNNAMED
- 使用标准库替代类,例如:
- 使用
java.util.Base64替代sun.misc.BASE64Encoder - 使用
VarHandle替代Unsafe实现原子操作
7.2 JVM性能调优策略
Java 11支持多种垃圾回收器(G1、ZGC、CMS等),合理选择GC策略和调优参数对应用性能至关重要。
7.2.1 垃圾回收器选择与参数优化
| 垃圾回收器 | 特点 | 适用场景 |
|---|---|---|
| G1 GC | 可预测停顿时间,适合大堆内存 | 通用场景,推荐 |
| ZGC | 亚毫秒级停顿,支持TB级堆 | 实时性要求高的服务 |
| CMS | 并发标记清除,低延迟 | 已不推荐使用 |
推荐G1配置示例:
-Xms4g -Xmx4g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:ParallelGCThreads=8
7.2.2 内存分配与GC日志分析
开启GC日志是性能调优的第一步:
-Xlog:gc*:file=gc.log:time
使用 jstat 工具查看GC状态:
jstat -gc <pid> 1000
分析GC日志常用工具:
- GCViewer
- GCEasy
- VisualVM
通过分析GC频率、停顿时间、堆内存变化,可以发现内存泄漏、频繁Full GC等问题,并针对性地调整堆大小、GC参数或优化对象生命周期。
7.3 应用性能提升技巧
Java 11新增的API和工具为性能优化提供了新的可能。合理使用这些特性,可以显著提升应用吞吐量和响应速度。
7.3.1 利用新API提升I/O与网络性能
Java 11的 HttpClient 支持异步请求和HTTP/2,适合高并发网络通信:
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
优势:
- 支持异步非阻塞模式
- 自动处理重定向与Cookie
- 简化HTTP通信流程
7.3.2 编译优化与运行时优化建议
- 使用
javac的-parameters参数保留方法参数名,便于反射使用:
javac -parameters MyClass.java
- 启用JIT编译优化:
-XX:+TieredCompilation -XX:TieredStopAtLevel=1
- 使用
@Contended注解避免伪共享(适用于多线程共享变量):
@jdk.internal.vm.annotation.Contended
private volatile int state;
7.4 持续集成与部署优化
在云原生环境下,Java 11的CI/CD流程也需要进行适配优化,提升部署效率与运行稳定性。
7.4.1 CI/CD流程中JDK 11的应用
在CI流程中使用SDKMAN或jEnv统一管理JDK版本:
# SDKMAN示例
sdk use java 11.0.22.hs-adpt
在Jenkins或GitHub Actions中配置Java 11构建环境:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: '11'
- name: Build with Maven
run: mvn clean package
7.4.2 与Kubernetes等云原生平台的适配策略
Java应用在Kubernetes中部署时,需注意资源限制与JVM内存设置的匹配:
resources:
limits:
memory: "2Gi"
cpu: "500m"
JVM启动参数应限制堆内存,避免OOMKilled:
-Xms1g -Xmx1g -XX:+UseContainerSupport
结合 JLink 构建的最小化JRE镜像可大幅减小容器体积,提升启动速度。
FROM custom-jre:11
COPY app.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
(本章节内容暂未总结,继续向下阅读下一章节)
简介:Java 11是由Oracle发布的Java开发工具集主要版本,属于长期支持(LTS)版本,具有良好的兼容性、安全性及稳定性。该版本在Java 8基础上引入了多项新特性,如HTTP客户端模块、动态语言支持、JVM Attach API改进、JLink和JPackage工具等。文章强调通过官方渠道统一下载的重要性,并详细介绍了安装配置流程与开发实践,适合企业级开发者和项目维护人员使用。
更多推荐



所有评论(0)