跳到主要内容
Java 25 LTS 核心特性详解:语言改进与性能优化 | 极客日志
Java java
Java 25 LTS 核心特性详解:语言改进与性能优化 综述由AI生成 Java 25 作为继 17 和 21 之后的第三个 LTS 版本,带来了 18 个 JEP 提案。语言层面引入紧凑源文件降低入门门槛,支持灵活构造器体执行前置逻辑,新增模块导入声明简化模块化开发,并增强原语类型模式匹配。库层面提供结构化并发简化线程管理,作用域值替代 ThreadLocal,向量 API 提升 SIMD 性能,以及密钥派生函数和 PEM 编码 API。性能方面,紧凑对象头减少内存占用,AOT 命令行优化加速启动。监控方面增强 JFR CPU 时间分析和协作采样。此外还有 HttpClient 增强、ForkJoinPool 改进及 G1 GC 优化。详细解析了这些特性及迁移指南。
DevOpsTeam 发布于 2026/3/27 更新于 2026/5/30 33 浏览前言
Java 25 于 2025 年 9 月 16 日正式发布,作为继 Java 17 和 Java 21 之后的第三个 LTS(长期支持)版本,它带来了 18 个 JEP(JDK Enhancement Proposals)提案,涵盖了语言、库、性能和监控等多个方面的重大改进。本文将深入解析 Java 25 的核心特性,帮助开发者全面了解这一版本的技术突破。
版本概览
版本 发布时间 主要特性 Java 17 LTS 2021 年 9 月 记录类、模式匹配预览、封装类 Java 21 LTS 2023 年 9 月 虚拟线程 (正式)、序列化集合、作用域值 (预览) Java 25 LTS 2025 年 9 月 紧凑源文件、灵活构造器体、模块导入声明、原语类型模式匹配
一、语言层面的重大改进
1.1 紧凑源文件和实例主方法(JEP 512)
这是 Java 25 中最令人兴奋的特性之一,它极大地简化了初学者的入门门槛,同时也让有经验的开发者能够更简洁地编写小程序。
传统写法:
public class HelloWorld {
public static void main (String[] args) {
System.out.println("Hello, World!" );
}
}
Java 25 紧凑写法:
void main () {
System.out.println("Hello, World!" );
}
完整特性演示:
String getGreeting (String name) {
return "Hello, " + name;
}
void main () {
System.out.println(getGreeting("Java 25" ));
}
演进路径:
初学者:无需理解类概念 -> 掌握基础后 -> 添加类声明 -> 经验丰富 -> 理解封装 -> 标准 Java 语法
快速原型开发:紧凑源文件 -> 逐步演进到标准形式
降低学习门槛 :初学者无需理解类、静态方法等概念即可开始编程
快速原型开发 :有经验的开发者可以快速编写测试代码和脚本
无缝演进 :程序可以逐步从紧凑形式演进到标准形式
1.2 灵活的构造器体(JEP 463) Java 25 允许在构造器体中,在显式构造器调用(super(...)或 this(...))之前执行语句。这使得许多构造器的表达更加自然。
public class Parent {
private final String name;
private final int age;
public Parent (String name, int age) {
this .name = name;
this .age = age;
}
}
public class Child extends Parent {
private final String displayName;
public Child (String name, int age) {
String computedName = name.toUpperCase();
super (computedName, age);
this .displayName = computedName;
}
}
public class Child extends Parent {
private final String displayName;
public Child (String name, int age) {
String computedName = name.toUpperCase();
this .displayName = computedName;
super (computedName, age);
}
public Child (String firstName, String lastName, int age) {
String fullName = computeFullName(firstName, lastName);
this .displayName = fullName;
if (age < 0 ) {
throw new IllegalArgumentException ("年龄不能为负数" );
}
super (fullName, age);
}
private String computeFullName (String first, String last) {
return (first + " " + last).trim();
}
}
在显式构造器调用之前的语句不能引用正在构造的对象
可以初始化字段和执行其他安全计算
字段在调用父类构造器之前完成初始化,提高了安全性
1.3 模块导入声明(JEP 511) Java 25 引入了模块导入声明,允许简洁地导入模块导出的所有包,大大简化了模块化库的重用。
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.stream.Stream;
import java.util.stream.Collectors;
public class Example {
}
import module java.base;
public class Example {
public void process () {
List<String> list = new ArrayList <>();
Map<String, Integer> map = new HashMap <>();
Set<Integer> set = new HashSet <>();
Stream<String> stream = list.stream();
}
}
import module java.sql;
public class DatabaseExample {
public void queryDatabase () throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb" );
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users" );
while (rs.next()) {
System.out.println(rs.getString("name" ));
}
}
}
简化导入语句,减少代码冗余
不需要将导入代码放在模块中
提高代码可读性
1.4 原语类型模式匹配(第三次预览) Java 25 进一步增强了模式匹配,允许在所有模式上下文中使用原语类型,并扩展了 instanceof和 switch以支持所有原语类型。
public void processNumber (Object obj) {
if (obj instanceof int i) {
System.out.println("整数:" + i);
} else if (obj instanceof long l) {
System.out.println("长整数:" + l);
} else if (obj instanceof double d) {
System.out.println("双精度:" + d);
}
}
public String getType (Object value) {
return switch (value) {
case int i -> "整数类型:" + i;
case long l -> "长整型:" + l;
case float f -> "浮点型:" + f;
case double d -> "双精度型:" + d;
default -> "其他类型" ;
};
}
record Point (int x, int y) {}
record Circle (Point center, int radius) {}
public void processShape (Object shape) {
if (shape instanceof Circle (Point(int x, int y) , int radius)) {
System.out.printf("圆心在 (%d,%d),半径为%d%n" , x, y, radius);
}
}
public String describeNumber (Object num) {
return switch (num) {
case int i when i > 0 -> "正整数:" + i;
case int i when i < 0 -> "负整数:" + i;
case int i -> "零" ;
case double d when d > 0 -> "正浮点数:" + d;
default -> "其他数值" ;
};
}
二、库层面的重要更新
2.1 结构化并发(第五次预览) 结构化并发将运行在不同线程中的相关任务组视为单个工作单元,从而简化了错误处理和取消操作,提高了可靠性和可观测性。
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.Future;
import java.util.function.Supplier;
public class StructuredConcurrencyExample {
public String fetchUserDataOldWay (String userId) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(3 );
try {
Future<String> userFuture = executor.submit(() -> fetchUser(userId));
Future<List<Order>> ordersFuture = executor.submit(() -> fetchOrders(userId));
Future<List<Review>> reviewsFuture = executor.submit(() -> fetchReviews(userId));
String user = userFuture.get();
List<Order> orders = ordersFuture.get();
List<Review> reviews = reviewsFuture.get();
return combineData(user, orders, reviews);
} finally {
executor.shutdown();
}
}
public String fetchUserDataNewWay (String userId) throws Exception {
try (var scope = new StructuredTaskScope .ShutdownOnFailure()) {
Supplier<String> userTask = scope.fork(() -> fetchUser(userId));
Supplier<List<Order>> ordersTask = scope.fork(() -> fetchOrders(userId));
Supplier<List<Review>> reviewsTask = scope.fork(() -> fetchReviews(userId));
scope.join().throwIfFailed();
return combineData(userTask.get(), ordersTask.get(), reviewsTask.get());
}
}
private String fetchUser (String userId) {
return "User: " + userId;
}
private List<Order> fetchOrders (String userId) {
return List.of(new Order ("order1" ), new Order ("order2" ));
}
private List<Review> fetchReviews (String userId) {
return List.of(new Review ("review1" ), new Review ("review2" ));
}
private String combineData (String user, List<Order> orders, List<Review> reviews) {
return user + ", Orders: " + orders.size() + ", Reviews: " + reviews.size();
}
}
自动资源管理 :使用 try-with-resources 自动管理任务生命周期
统一错误处理 :任一任务失败自动取消其他任务
可观测性 :更容易跟踪和调试并发任务
取消传播 :父任务取消时自动取消子任务
2.2 作用域值(Scoped Values) 作用域值允许方法在其线程内与被调用者共享不可变数据,也可以与子线程共享。相比 ThreadLocal,作用域值更易于理解,空间和时间开销更低。
public class ThreadLocalExample {
private static final ThreadLocal<String> CONTEXT = new ThreadLocal <>();
public void processRequest (String requestId) {
CONTEXT.set(requestId);
try {
process1();
process2();
} finally {
CONTEXT.remove();
}
}
private void process1 () {
String id = CONTEXT.get();
System.out.println("Process1: " + id);
}
private void process2 () {
String id = CONTEXT.get();
System.out.println("Process2: " + id);
}
}
public class ScopedValueExample {
private static final ScopedValue<String> REQUEST_ID = new ScopedValue <>();
public void processRequest (String requestId) {
ScopedValue.where(REQUEST_ID, requestId).run(() -> {
process1();
process2();
});
}
private void process1 () {
String id = REQUEST_ID.get();
System.out.println("Process1: " + id);
}
private void process2 () {
String id = REQUEST_ID.get();
System.out.println("Process2: " + id);
}
}
public class VirtualThreadWithScopedValue {
private static final ScopedValue<String> CONTEXT = new ScopedValue <>();
public void handleRequest (String requestId) {
ScopedValue.where(CONTEXT, requestId).run(() -> {
System.out.println("Main: " + CONTEXT.get());
Thread.startVirtualThread(() -> {
System.out.println("Virtual Thread: " + CONTEXT.get());
});
});
}
}
public class NestedScopes {
private static final ScopedValue<String> LEVEL1 = new ScopedValue <>();
private static final ScopedValue<String> LEVEL2 = new ScopedValue <>();
public void nestedExample () {
ScopedValue.where(LEVEL1, "Outer" ).run(() -> {
System.out.println("Level 1: " + LEVEL1.get());
ScopedValue.where(LEVEL1, "Inner" ).run(() -> {
System.out.println("Level 1: " + LEVEL1.get());
ScopedValue.where(LEVEL2, "Deep" ).run(() -> {
System.out.println("Level 1: " + LEVEL1.get());
System.out.println("Level 2: " + LEVEL2.get());
});
});
System.out.println("Level 1: " + LEVEL1.get());
});
}
}
2.3 稳定值(Stable Values,预览) 稳定值 API 引入了保存不可变数据的对象,JVM 将稳定值视为常量,从而实现与声明 final 字段相同的性能优化。相比 final 字段,稳定值在初始化时机上更加灵活。
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
public class StableValueExample {
private final String fixedValue = "Fixed" ;
private static final StableValue<String> LAZY_VALUE = StableValue.of(() -> {
return "Computed: " + System.currentTimeMillis();
});
private static final VarHandle STABLE_HANDLE = MethodHandles.lookup().findVarHandle(StableValueExample.class, "stableField" , String.class);
private volatile String stableField;
public void demonstrateStableValue () {
String value = LAZY_VALUE.get();
System.out.println("Stable value: " + value);
for (int i = 0 ; i < 1000 ; i++) {
processValue(value);
}
}
private void processValue (String value) {
}
}
延迟初始化的全局配置
缓存不可变计算结果
优化频繁访问的常量数据
2.4 向量 API(第十次孵化) 向量 API 允许开发者表达向量计算,这些计算在运行时可靠地编译为支持 CPU 上的最优向量指令,从而实现优于等效标量计算的性能。
import jdk.incubator.vector.*;
import java.util.Arrays;
public class VectorAPIExample {
public void scalarMultiply (float [] a, float [] b, float [] c) {
for (int i = 0 ; i < a.length; i++) {
c[i] = a[i] * b[i];
}
}
public void vectorMultiply (float [] a, float [] b, float [] c) {
int speciesLength = FloatVector.SPECIES_PREFERRED.length();
int i = 0 ;
for (; i < a.length - speciesLength; i += speciesLength) {
var va = FloatVector.fromArray(FloatVector.SPECIES_PREFERRED, a, i);
var vb = FloatVector.fromArray(FloatVector.SPECIES_PREFERRED, b, i);
var vc = va.mul(vb);
vc.intoArray(c, i);
}
for (; i < a.length; i++) {
c[i] = a[i] * b[i];
}
}
public float [] vectorCompute(float [] data) {
int length = data.length;
float [] result = new float [length];
int speciesLength = FloatVector.SPECIES_PREFERRED.length();
int i = 0 ;
for (; i < length - speciesLength; i += speciesLength) {
var v = FloatVector.fromArray(FloatVector.SPECIES_PREFERRED, data, i);
var squared = v.mul(v);
var plusOne = squared.add(1.0f );
var sum = plusOne.reduceLanes(VectorOperators.ADD);
var broadcast = FloatVector.broadcast(FloatVector.SPECIES_PREFERRED, sum);
broadcast.intoArray(result, i);
}
return result;
}
}
指标 标量计算 向量计算 CPU 占用 100% 100% SIMD 并行 耗时 基准 0.25x-0.5x
2.5 密钥派生函数 API(JEP 510) Java 25 引入了密钥派生函数(KDF)API,这些是从密钥和其他数据派生其他密钥的加密算法。
import javax.crypto.*;
import javax.crypto.spec.*;
public class KDFExample {
public void deriveKeys () throws Exception {
SecretKey masterKey = generateMasterKey();
SecretKey encryptionKey = deriveKey(masterKey, "encryption" , 256 );
SecretKey authKey = deriveKey(masterKey, "authentication" , 256 );
SecretKey hmacKey = deriveKey(masterKey, "hmac" , 512 );
System.out.println("Encryption Key: " + encryptionKey.getAlgorithm());
System.out.println("Auth Key: " + authKey.getAlgorithm());
System.out.println("HMAC Key: " + hmacKey.getAlgorithm());
}
private SecretKey deriveKey (SecretKey masterKey, String purpose, int length) throws Exception {
KDF kdf = KDF.getInstance("HKDF-SHA256" );
KDFParameters params = new KDFParameters .Builder()
.setKey(masterKey)
.setSalt(purpose.getBytes())
.setInfo(purpose.getBytes())
.setLength(length / 8 )
.build();
return kdf.deriveKey("AES" , params);
}
private SecretKey generateMasterKey () throws Exception {
KeyGenerator keyGen = KeyGenerator.getInstance("AES" );
keyGen.init(256 );
return keyGen.generateKey();
}
}
从主密钥派生多个子密钥
密钥轮换
分层密钥管理
安全通信协议
2.6 PEM 编码(预览) 引入了 API,用于将代表加密密钥、证书和证书吊销列表的对象编码为广泛使用的隐私增强邮件(PEM)传输格式,并从该格式解码回对象。
import java.security.cert.*;
import java.security.*;
import java.util.Base64;
public class PEMExample {
public void encodeKeyToPEM () throws Exception {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA" );
keyGen.initialize(2048 );
KeyPair keyPair = keyGen.generateKeyPair();
PEMEncoder encoder = new PEMEncoder ();
String privateKeyPEM = encoder.encode(keyPair.getPrivate());
System.out.println("Private Key PEM:\n" + privateKeyPEM);
String publicKeyPEM = encoder.encode(keyPair.getPublic());
System.out.println("Public Key PEM:\n" + publicKeyPEM);
}
public void decodeCertificateFromPEM (String pemCertificate) throws Exception {
PEMDecoder decoder = new PEMDecoder ();
Certificate cert = decoder.decodeCertificate(pemCertificate);
System.out.println("Certificate Subject: " + ((X509Certificate) cert).getSubjectDN());
}
public void encodeCertificateToPEM (X509Certificate cert) throws Exception {
PEMEncoder encoder = new PEMEncoder ();
String pem = encoder.encode(cert);
System.out.println("Certificate PEM:\n" + pem);
}
}
三、性能优化
3.1 紧凑对象头(JEP 519) Java 25 将紧凑对象头从实验特性转为产品特性,显著减少 Java 堆内存占用,并提供潜在的性能提升。
传统对象头:Mark Word (8 字节) + Klass Pointer (4/8 字节) = 12-16 字节
紧凑对象头:压缩 Mark Word (4 字节) + 压缩 Klass Pointer (4 字节) = 8 字节
节省:25-50%
java -XX:+UseCompactObjectHeaders MyApp
java -XX:-UseCompactObjectHeaders MyApp
public class CompactObjectExample {
private static class SmallObject {
int value;
String name;
}
public void memoryComparison () {
List<SmallObject> objects = new ArrayList <>();
for (int i = 0 ; i < 1_000_000 ; i++) {
objects.add(new SmallObject ());
}
}
}
3.2 AOT 命令行优化(JEP 514) 简化了创建 AOT 缓存所需的命令,这些缓存可以加速 Java 应用的启动。
java -XX:ArchiveClassesAtExit=app.jsa -cp myapp.jar MyApp
java -XX:SharedArchiveFile=app.jsa -cp myapp.jar MyApp
java -aot:create -o myapp.aot -cp myapp.jar MyApp
java -aot:use -i myapp.aot -cp myapp.jar MyApp
java -aot:create -o cache.aot -cp lib/*:myapp.jar com.example.Main
java -aot:use -i cache.aot -cp lib/*:myapp.jar com.example.Main
3.3 AOT 方法性能分析(JEP 515) 通过在 HotSpot JVM 启动时立即可用上一次运行的方法执行配置文件,改善预热时间,使 JIT 编译器能够在应用启动时立即生成本地代码。
java -XX:ProfilesAtExit=profile.jfr MyApp
java -XX:ProfilesDumpFile=profile.jfr MyApp
AOT 性能分析启动:预热时间 1-3 秒,加载性能分析后直接 C2 编译至最佳性能
传统启动:预热时间 10-30 秒,解释执行 -> C1 编译 -> C2 编译至最佳性能
四、监控与诊断增强
4.1 JFR CPU 时间性能分析(实验性) 增强了 JDK Flight Recorder(JFR),在 Linux 上捕获更准确的 CPU 时间性能分析信息。
java -XX:StartFlightRecording=filename=recording.jfr,duration=60s,cpu-profiling=true MyApp
jfr print --events cpu,jdk.CPUInformation recording.jfr
4.2 JFR 协作采样 改进 JFR 在异步采样 Java 线程堆栈时的稳定性,通过仅在安全点遍历调用堆栈,同时最小化安全点偏差。
import jdk.jfr.*;
@Name("custom.event")
@Label("自定义事件")
public class CustomEvent extends Event {
@Label("消息") String message;
@Label("持续时间") long duration;
}
public class JFRCooperativeSampling {
public void recordEvent () {
CustomEvent event = new CustomEvent ();
event.message = "操作完成" ;
event.duration = System.nanoTime();
event.commit();
processWork();
}
private void processWork () {
}
}
4.3 JFR 方法计时和跟踪 通过字节码增强扩展 JFR,提供方法计时和跟踪功能。
java -XX:StartFlightRecording=method-profiling=true ,stack-depth=16 MyApp
jfr print --events jdk.ExecutionSample recording.jfr
import jdk.jfr.*;
@Name("method.timing")
@Label("方法计时")
public class MethodTimingEvent extends Event {
@Label("类名") String className;
@Label("方法名") String methodName;
@Label("执行时间 (纳秒)") long duration;
}
public class MethodProfiling {
@StackTrace(false)
public void profileMethod () {
long start = System.nanoTime();
try {
doWork();
} finally {
long duration = System.nanoTime() - start;
MethodTimingEvent event = new MethodTimingEvent ();
event.className = this .getClass().getName();
event.methodName = "profileMethod" ;
event.duration = duration;
event.commit();
}
}
private void doWork () {
}
}
五、其他重要改进
5.1 HttpClient API 增强 import java.net.http.*;
import java.net.URI;
public class HttpClientEnhancements {
public void fetchWithSizeLimit () throws Exception {
HttpClient client = HttpClient.newHttpClient();
BodyHandler<String> limitedHandler = BodyHandlers.limiting(BodyHandlers.ofString(), 1024 * 1024 );
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data" ))
.build();
HttpResponse<String> response = client.send(request, limitedHandler);
System.out.println("Response body length: " + response.body().length());
}
public void getConnectionInfo () throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request1 = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/endpoint1" ))
.build();
HttpRequest request2 = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/endpoint2" ))
.build();
HttpResponse<String> response1 = client.send(request1, BodyHandlers.ofString());
HttpResponse<String> response2 = client.send(request2, BodyHandlers.ofString());
Object label1 = response1.connectionLabel();
Object label2 = response2.connectionLabel();
if (label1.equals(label2)) {
System.out.println("两个请求使用相同的连接" );
} else {
System.out.println("两个请求使用不同的连接" );
}
}
}
5.2 ForkJoinPool 改进 ForkJoinPool 现在实现了 ScheduledExecutorService 接口,提高了延迟任务处理的性能。
import java.util.concurrent.*;
public class ForkJoinPoolImprovements {
public void scheduleWithForkJoinPool () {
ForkJoinPool pool = new ForkJoinPool ();
ScheduledFuture<?> future = pool.schedule(() -> {
System.out.println("延迟任务执行" );
}, 5 , TimeUnit.SECONDS);
CompletableFuture<String> result = pool.submitWithTimeout(() -> {
Thread.sleep(3000 );
return "任务完成" ;
}, 2 , TimeUnit.SECONDS);
result.exceptionally(ex -> {
System.out.println("任务超时:" + ex.getMessage());
return "默认值" ;
});
}
}
5.3 G1 垃圾收集器优化 G1 垃圾收集器进一步减少了记忆集内存开销和暂停时间,通过允许多个区域在混合 GC 期间共享单个内部结构。
传统 G1:Region 1, 2, 3, 4 分别对应 G1CardSet 1, 2, 3, 4,内存开销高
优化 G1:Region 1, 2, 3, 4 共享 G1CardSet,内存开销低
减少混合 GC 的暂停时间
降低记忆集内存占用
提高内存效率
5.4 新增系统属性 添加了 stdin.encoding 系统属性,用于指定从 System.in 读取字符数据时的推荐字符集。
import java.util.Scanner;
public class EncodingExample {
public void readUserInput () {
String stdinEncoding = System.getProperty("stdin.encoding" );
System.out.println("stdin.encoding: " + stdinEncoding);
Scanner scanner = new Scanner (System.in, stdinEncoding);
System.out.print("请输入:" );
String input = scanner.nextLine();
System.out.println("输入内容:" + input);
}
}
六、迁移指南
6.1 从 Java 21 升级到 Java 25
javac --release 21 -Xlint:unchecked YourClass.java
紧凑对象头 :默认禁用,建议测试后启用
已移除功能 :Graal JIT 编译器已移除
已弃用功能 :UseCompressedClassPointers 选项已弃用
6.2 最佳实践
逐步采用新特性 :
从紧凑源文件开始,简化小程序开发
在新项目中使用灵活构造器体
考虑使用结构化并发替代传统线程管理
性能优化 :
启用紧凑对象头减少内存占用
使用 AOT 缓存加速启动
利用 JFR 增强的监控功能
安全增强 :
使用新的 KDF API 进行密钥管理
利用 PEM 编码简化证书处理
使用 HttpClient 的大小限制功能
七、总结 Java 25 作为一个重要的 LTS 版本,带来了诸多令人兴奋的改进:
紧凑源文件极大降低了学习门槛
灵活构造器体使代码更自然
模块导入简化了库的使用
原语类型模式匹配增强了类型安全
结构化并发简化了并发编程
作用域值提供了更好的线程间数据共享
向量 API 提供了 SIMD 性能优化
新的加密 API 增强了安全性
紧凑对象头减少内存占用
AOT 优化加速应用启动
G1 垃圾收集器进一步优化
JFR 增强了性能分析能力
更准确的 CPU 时间采样
方法计时和跟踪功能
Java 25 不仅保持了 Java 的稳定性和向后兼容性,还通过这些新特性为开发者提供了更强大的工具,使得 Java 在现代应用开发中继续保持竞争力。无论是初学者还是经验丰富的开发者,都能从这些改进中受益。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online