Arthas: 使用arthas-boot时打印对象有乱码

Created on 17 Dec 2018  ·  11Comments  ·  Source: alibaba/arthas

  • [x] 我已经在 issues 里搜索,没有重复的issue。

环境信息

  • arthas-boot.jar 的版本: 3.0.5.1
  • 操作系统版本: Linux 3.10.0-862.2.3.el7.x86_64
  • 目标进程的JDK版本: 1.8
  • 目标进程的JVM版本: 25.144-b01
  • 系统字符集如下图
    image
    image

重现问题的步骤

  1. 启动demo工程
  2. arthas监听接口接收的中文参数
  3. arthas监听接口返回的中文内容
  4. curl接口请求http://localhost:8080/test/hello?params=%E4%BD%A0%E5%A5%BD

image

image

监听的demo是基于spring boot 2.1.1.RELEASE开发的,代码如下
demo2018.zip

期望的结果

中文正常显示

实际运行的结果

中文乱码
image

但是通过telnet连接arthas监控则正常显示中文
image

bug

Most helpful comment

这里有一个修复版,需要的可以测试下:arthas-3.0.6-SNAPSHOT-bin.zip

All 11 comments

乱码原因分析:

  • 无论用native telnet,还是arthas-boot java telnet来连接,通过抓包,返回的数据流都是对的,都是utf-8编码

    00000000  74 73 3d 32 30 31 38 2d  31 32 2d 31 38 20 30 30   ts=2018- 12-18 00
    00000010  3a 33 39 3a 34 35 3b 20  5b 63 6f 73 74 3d 30 2e   :39:45;  [cost=0.
    00000020  35 31 31 35 6d 73 5d 20  72 65 73 75 6c 74 3d 40   5115ms]  result=@
    00000030  4f 62 6a 65 63 74 5b 5d  5b                        Object[] [
    00000039  0d 0a                                              ..
    0000003B  20 20 20 20 40 53 74 72  69 6e 67 5b e4 bd a0 e5       @Str ing[....
    0000004B  a5 bd 5d 2c                                        ..],
    0000004F  0d 0a                                              ..
    00000051  5d                                                 ]
    00000052  0d 0a                                              ..
    

    你好的utf-8编码是: E4BDA0E5A5BD

  • 但是在 arthas-boot里,最终打印到终端却是乱码

  • 在arthas-boot里,用socket里读取数据,再通过consoleReader.getOutput()输出到终端上

                    IOUtil.readWrite(telnet.getInputStream(), telnet.getOutputStream(), System.in,
                                    consoleReader.getOutput());
    
  • consoleReader.getOutput()实际上是一个Writer类,它接收的其实是一个char,所以在IOUtil里实际上转换出错了。从telnet.getInputStream()不断读出byte,然后却是强制转换为一个char来写出到output writer里。一个UTF8字符可能有多个byte(1到5个),则写入了多个char(应该是一个char或者两个char),这样子就会出现乱码。

    https://github.com/alibaba/arthas/blob/arthas-all-3.0.5/client/src/main/java/com/taobao/arthas/client/IOUtil.java#L49

    如果这个能把IOUtil的4个参数统一为 InputStream, OutputStream 也不会有问题。但是consoleReader.getOutput()只返回Writer接口。所以在 IOUtil 需要把InputStream转换为 InputStreamReader,这样子就不会有问题了。InputStreamReader每次返回的都是一个char,和Writer对应。

所以最终解决办法是把InputStream转换一次为InputStreamReader

这里有一个修复版,需要的可以测试下:arthas-3.0.6-SNAPSHOT-bin.zip

这里有一个修复版,需要的可以测试下:arthas-3.0.6-SNAPSHOT-bin.zip

it works!

你好,我用修复版还是一样
系统:window 7
dubbox消费者调用,监控消费者收到的返回值

public interface CustomGenerate {
    String generate(String name);
}

命令

watch com.alibaba.dubbo.common.bytecode.proxy4 generate returnObj

打印结果如下

ts=2018-12-28 17:56:36; [cost=1.351749ms] result=@String[???????????????:??????]

你好,我用修复版还是一样
系统:window 7
dubbox消费者调用,监控消费者收到的返回值

public interface CustomGenerate {
    String generate(String name);
}

命令

watch com.alibaba.dubbo.common.bytecode.proxy4 generate returnObj

打印结果如下

ts=2018-12-28 17:56:36; [cost=1.351749ms] result=@String[???????????????:??????]

执行这两个命令,看输出是什么:

sysprop | grep encoding
sysenv | grep LANG

你好,我用修复版还是一样
系统:window 7
dubbox消费者调用,监控消费者收到的返回值

public interface CustomGenerate {
    String generate(String name);
}

命令

watch com.alibaba.dubbo.common.bytecode.proxy4 generate returnObj

打印结果如下

ts=2018-12-28 17:56:36; [cost=1.351749ms] result=@String[???????????????:??????]

执行这两个命令,看输出是什么:

sysprop | grep encoding
sysenv | grep LANG

第一个命令结果:
sysprop | grep encoding

 file.encoding.pkg        sun.io
 sun.jnu.encoding         GBK
 file.encoding            UTF-8
 sun.io.unicode.encoding  UnicodeLittle

把项目改成GBK后 两个都是GBK了 还是乱码
第二个命令结果:
sysenv | grep LANG

 ERLANG_HOME              F:\erl9.0

@ergehenmeng 试下 telnet localhost 3658 看是否乱码

@ergehenmeng 试下 telnet localhost 3658 看是否乱码
感谢大佬那么晚还回复

ts=2018-12-29 09:44:51; [cost=6.936157ms] result=@String[鏈嶅姟绔硾鍖?浜斿摜]

又修改cmd字符集为UTF-8变成

ts=2018-12-29 09:50:12; [cost=5.57176ms] result=@String[               :      ]

@ergehenmeng 试下 telnet localhost 3658 看是否乱码
感谢大佬那么晚还回复

ts=2018-12-29 09:44:51; [cost=6.936157ms] result=@String[鏈嶅姟绔硾鍖?浜斿摜]

又修改cmd字符集为UTF-8变成

ts=2018-12-29 09:50:12; [cost=5.57176ms] result=@String[               :      ]

telnet都乱码,可能就是shell设置的问题。 可以试下 java -jar -Dfile.encoding=gbk arthas-client.jar ,用这个java的 telnet client来连接,看下怎样。

@ergehenmeng 试下 telnet localhost 3658 看是否乱码
感谢大佬那么晚还回复

ts=2018-12-29 09:44:51; [cost=6.936157ms] result=@String[鏈嶅姟绔硾鍖?浜斿摜]

又修改cmd字符集为UTF-8变成

ts=2018-12-29 09:50:12; [cost=5.57176ms] result=@String[               :      ]

telnet都乱码,可能就是shell设置的问题。 可以试下 java -jar -Dfile.encoding=gbk arthas-client.jar ,用这个java的 telnet client来连接,看下怎样。

结果依旧是

ts=2018-12-29 14:33:13; [cost=5.183564ms] result=@String[鏈嶅姟绔硾鍖?:浜斿摜]

我把所有涉及字符集的互换组合,更乱了,
arthas或者cmd把utf-8转成gbk,个人感觉应arthas可能性更大 ,如果arthas以unicode显示打印结果就好了

Was this page helpful?
0 / 5 - 0 ratings