charset.availablecharsets() 返回一个只读的sortedmap,键为字符集标准名称(如"utf-8"),值为对应charset实例;它仅包含jvm已加载注册的字符集,不保证涵盖所有可能编码,且名称区分大小写。

Charset.availableCharsets() 返回的是什么
它返回一个 SortedMap<string charset></string>,键是字符集的标准名称(比如 "UTF-8"、"GBK"),值是对应的 Charset 实例。注意:这个 Map 是只读的,直接调用 put 会抛 UnsupportedOperationException。
常见误解是以为它列出“系统能识别的所有编码”,其实只是当前 JVM **已加载且注册** 的字符集 —— 比如某些自定义或第三方 CharsetProvider 提供的编码,如果没被触发加载,就不会出现在结果里。
- 启动时默认加载核心字符集(
US-ASCII、UTF-8、ISO-8859-1等) - 部分字符集(如
Big5、Shift_JIS)在 Oracle JDK 中存在,但在某些精简版 JRE 或 GraalVM 原生镜像中可能被裁剪掉 - 调用该方法本身不触发类加载,但 Map 中的
Charset实例已是初始化完成的状态
为什么有时候看不到 GBK 或 GB2312
不是 JVM 不支持,而是你运行的环境没加载对应实现。Oracle JDK 和 OpenJDK 主流版本都内置了 GBK,但如果用了 --strip-debug、--exclude-files 打包,或使用了自定义 CharsetProvider 并未注册这些别名,就可能缺失。
更常见的情况是:代码里写的是 "gbk"(小写),而 availableCharsets() 里存的是 "GBK"(大写)。Java 字符集名称区分大小写,但 Charset.forName() 是不区分的 —— 这个差异容易让人误判“没这个编码”。
立即学习“Java免费学习笔记(深入)”;
- 检查是否真缺失:
Charset.isSupported("GBK")比遍历 Map 更可靠 - 别依赖 Map 的 key 集合做用户可选列表,因为别名(如
"windows-936")不一定包含在内 - 某些 Android Runtime(ART)或旧版 Harmony JVM 不提供完整实现,
availableCharsets()可能只有 5–6 个
在 Spring Boot 或 Tomcat 中获取可用字符集要注意什么
Web 容器常会提前注册额外字符集(比如 Tomcat 的 org.apache.tomcat.util.buf.UDecoder 会加载 ISO-8859-1 相关逻辑),但这些不影响 Charset.availableCharsets() 的结果 —— 它只反映 java.nio.charset 层的注册状态。
Spring Boot 的 StringHttpMessageConverter 默认只支持 UTF-8、ISO-8859-1、US-ASCII,即使 availableCharsets() 里有 "GBK",HTTP 请求头里写了 charset=gbk,也不代表 Spring 会自动用它解码请求体。
- 不要用
availableCharsets().keySet()动态配置 Web 编码白名单,容易引入不安全的编码(如"x-java-iso-8859-1") - Tomcat 9+ 默认禁用
CP1252等非标准别名,但availableCharsets()仍可能返回它们 - 若需扩展支持,应显式调用
CharsetProvider的register方法,而非指望自动发现
性能和线程安全问题
这个方法是线程安全的,返回的 Map 是内部缓存的不可变快照,多次调用开销极小。但它不是廉价操作 —— 第一次调用会触发所有已知 CharsetProvider 的扫描,可能涉及类路径扫描和静态初始化。
真正容易被忽略的是:如果你在高频日志、过滤器或序列化工具里反复调用它(比如每次 HTTP 请求都执行一次),虽然单次很快,但累积起来会成为 GC 和类加载的小负担,尤其在容器化部署、冷启动频繁的场景下。
- 建议在应用启动时缓存一次结果(比如放到
static finalMap 中) - 避免在
toString()、hashCode()或日志格式化参数里隐式调用它 - 如果只是判断某个编码是否存在,直接用
Charset.isSupported("xxx"),比遍历整个 Map 快得多
最麻烦的不是找不到某个字符集,而是你以为它存在、用它做了转换,结果在另一台机器上跑失败 —— 因为那台机器的 JVM 构建方式不同。别信文档,用 isSupported 校验,用实际字节测行为。










