网上有很多说出了解决办法的文章,却没有分析原因,解决方法是idea的settings
VM Options中加入-Dfile.encoding=GBK或者GB2312,这样乱码就会是正确的汉字,BUT!!!,为什么呢?
原因分析
- idea与maven怎么交互的
C:\Java\jdk1.8.0_162\bin\java.exe -Dmaven.multiModuleProjectDirectory=C:\projects\testweb
"-Dmaven.home=C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3.3\plugins\maven\lib\maven3"
"-Dclassworlds.conf=C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3.3\plugins\maven\lib\maven3\bin\m2.conf"
"-Dmaven.ext.class.path=C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3.3\plugins\maven\lib\maven-event-listener.jar"
"-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3.3\lib\idea_rt.jar=2669:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3.3\bin"
-Dfile.encoding=UTF-8
-classpath "C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.3.3\plugins\maven\lib\maven3\boot\plexus-classworlds-2.6.0.jar" org.codehaus.classworlds.Launcher -Didea.version2019.3.3 compile
为了看清楚我加了换行,-D参数有空格的,都会使用双引号包起来。 这是个java进程,入口是org.codehaus.classworlds.Launcher
- Launcher分析
org.codehaus.plexus.classworlds.launcher.Launcher.main( args );
String CLASSWORLDS_CONF = "classworlds.conf";
注意上面命令行有对应配置,是m2.conf,内容如下:
main is org.apache.maven.cli.MavenCli from plexus.core
set maven.conf default ${maven.home}/conf
[plexus.core]
load ${maven.conf}/logging
optionally ${maven.home}/lib/ext/*.jar
load ${maven.home}/lib/*.jar
其实就是调用到MavenCli,参数同样传递过去,compile
- Maven怎么编译代码的?
使用Apache Maven Compiler Plugin插件编译
The Compiler Plugin is used to compile the sources of your project. Since 3.0, the default compiler is javax.tools.JavaCompiler (if you are using java 1.6) and is used to compile Java sources. If you want to force the plugin using javac, you must configure the plugin option forceJavacCompilerUse.
- javac的问题
我们用javac,其实也是用javax.tools.JavaCompiler,那么在windows下,本地的编码是GBK,默认输出的汉语信息编码就是GBK,如何强制设为UTF-8呢?
用法: javac <options> <source files>
其中, 可能的选项包括:
@<filename> 从文件读取选项和文件名
-Akey[=value] 传递给注释处理程序的选项
--add-modules <模块>(,<模块>)*
除了初始模块之外要解析的根模块; 如果 <module>
为 ALL-MODULE-PATH, 则为模块路径中的所有模块。
--boot-class-path <path>, -bootclasspath <path>
覆盖引导类文件的位置
--class-path <path>, -classpath <path>, -cp <path>
指定查找用户类文件和注释处理程序的位置
-d <directory> 指定放置生成的类文件的位置
-deprecation 输出使用已过时的 API 的源位置
--enable-preview 启用预览语言功能。要与 -source 或 --release 一起使用。
-encoding <encoding> 指定源文件使用的字符编码
-endorseddirs <dirs> 覆盖签名的标准路径的位置
-extdirs <dirs> 覆盖所安装扩展的位置
-g 生成所有调试信息
-g:{lines,vars,source} 只生成某些调试信息
-g:none 不生成任何调试信息
-h <directory> 指定放置生成的本机标头文件的位置
--help, -help, -? 输出此帮助消息
--help-extra, -X 输出额外选项的帮助
-implicit:{none,class} 指定是否为隐式引用文件生成类文件
-J<flag> 直接将 <标记> 传递给运行时系统
--limit-modules <模块>(,<模块>)*
限制可观察模块的领域
--module <module-name>, -m <module-name>
注意有一个-J<flag>参数,我们可以-J-Dfile.encoding=UTF-8,这样,javac输出的信息就是UTF-8编码了
- 能不能给maven compiler plugin传参?
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<fork>true</fork>
<compilerArgs>
<arg>-J-Dfile.encoding=UTF-8</arg>
</compilerArgs>
</configuration>
</plugin>
- -Dfile.encoding解析
大家都知道这个参数,在jvm内存中,无论是英文字符还是中文字符,其实就是一个char,char是一个两个字节的数字,可以代表一个字符(java9之后字符串有变化,字符串不再是char数组了),当我们要把这个char写出去的时候,无论是写出到文件,还是socket,还是命令行,就要给它编码,这时候就用到这个参数了,指定写出的编码方案,同样,当jvm加载类读取字符串的时候,其实就是一个读取解码的过程,class文件用unicode编码,所以javac中有个选项-encoding,指定源文件的编码方案,无论源文件用什么字符集,到class文件里都是unicode,可以用支持16进制的文本编辑器打开class文件分析一下。
当从jvm写出东西的时候,我们也可以指定编码,getBytes(Charset.forName("UTF-8"));
This property is used for the default encoding in Java, all readers and writers would default to use this property. “file.encoding” is set to the default locale of Windows operationg system since Java 1.4.2. System.getProperty(“file.encoding”) can be used to access this property.
感兴趣可以分析一下maven compiler plugin的源码,或者使用别的编译器
来源:oschina
链接:https://my.oschina.net/wuxiaofei/blog/3215459