问题现象:在进行宝蓝德适配时发现主机的授权信息中客户名称和部门名称展示为乱码 针对该问题进行分析现象如下分析思路分析乱码的原因分析获取的该参数的值方法publicString getBin(Pointer lic, String column) {Pointer buf newMemory(256);IntByReference bufsize newIntByReference();bufsize.setValue(256);if(INSTANCE.license_get_bin(lic, column, buf, bufsize) 0) {return;}byte[] value buf.getByteArray(0, bufsize.getValue());returnnewString(value);}可以看出就是通过jni函数获取对应字段的byte数组转换为字符串通过远程debug连接后发现获取的字符串发现确实是乱码 进一步分析从jni中获取的byte数组列表得到的数据为[-28, -72, -83, -24, -81, -107, -25, -84, -74, -23, -98, -81, -26, -104, -112] 通过ai分析得到如下结果这组byte按 UTF-8解码对应的字符串是测试服务器可用下面代码验证byte[] b newbyte[] {-28, -72, -83, -24, -81, -107, -25, -84, -74, -23, -98, -81, -26, -104, -112};System.out.println(newString(b, StandardCharsets.UTF_8));说明byte数组转换为字符串确实为预期的值只能说明是new String(value);时使用到java进程的默认字符集导致的即对应的字符集非UTF-8编码分析默认编码为何非预期UTF-8需要分析默认的charset的获取方式阅读Charset的源码中可以看到是通过读取file.encoding的property获取。publicstaticCharset defaultCharset() {if(defaultCharset null) {synchronized(Charset.class) {String csn AccessController.doPrivileged(newGetPropertyAction(file.encoding));Charset cs lookup(csn);if(cs !null)defaultCharset cs;elsedefaultCharset forName(UTF-8);}}returndefaultCharset;}通过arthas工具查看问题节点的file.encoding非UTF-8编码而为ANSI_X3.4-1968类型。接下来分析file.encoding是如何设置的通过分析jdk和从AI结合分析得到在jvm启动时会尝试从本地的locale中获取会从LC_CTYPE中获取encoding信息实际实现为en_US.UTF-8 设置encoding就是UTF-8 部分有兴趣的可以设置LC_CTYPE参数查询file.encoding值。具体jdk代码如下setlocale(LC_ALL,);if(ParseLocale(env, LC_CTYPE,(sprops.format_language),(sprops.format_script),(sprops.format_country),(sprops.format_variant),(sprops.encoding))在bash中执行locale命令 获取到的locale输出却是utf-8类型综合现象和默认值对比只能是启动java进程的进程上下文中配置的locale被单独设置导致的在进程启动脚本中添加输出locale的日志发现确实被修改为POSIX了非xxx.utf-8.解决方案方案一 在bes.sh执行启动bes程序前设置locale为UTF-8编码即可。方案二 已知会从系统properties中获取可以加-Dfile.encodingUTF-8参数的方式设置总结1、为了保障程序的通用性如果已知字符集时new String IO流操作场景最好都配置上字符集2、程序设计时注意程序设置环境变量或参数对子进程的影响。