lizongbo at 618119.com 工作,生活,Android,前端,Linode,Ubuntu,nginx,java,apache,tomcat,Resin,mina,Hessian,XMPP,RPC

2009年04月12日

Windows下编写google app engine jsp出现中文乱码问题的真正原因

Filed under: Java — 标签:, , , , — lizongbo @ 12:54

Windows下编写google app engine jsp出现中文乱码问题的真正原因,是com.google.appengine.tools.admin.Application里启动javac没加-encoding参数导致.

在Linux下,因为一般都是LANG=zh_CN.UTF-8,因此就不会遇到这个问题了。

Windows下一般是取的默认的file.encoding为GBK,因此根据jsp生成的class文件就是乱码内容了。

验证流程如下:
1.首先重命名E:\\appengine--sdk-1.2.0\lib\shared\\jasper-compiler-5.0.28.jar为 jasper-compiler-5.0.28.jar.bak。
然后在E:\Java\appengine-java-sdk-1.2.0\bin下运行 appcfg update E:\Java\workspace\testwe\war。
这个时候在命令行下会看到如下的出错信息。
E:\Java\appengine-java-sdk-1.2.0\bin>java -cp “E:\Java\appengine-java-sdk-1.2.0\bin\\..\lib\appengine-tools-api.jar” com.google.appengine.tools.admin.AppCfg update e:\Java\workspace\testweb\war
Reading application configuration data…
2009-04-12 03:05:34.240::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
Beginning server interaction for lizongbo…
0% Creating staging directory
5% Scanning for jsp files.
8% Compiling jsp files.
Exception in thread “main” java.lang.NoClassDefFoundError: org/apache/jasper/
at com.google.appengine.tools.development.LocalJspC.main(LocalJspC.java:
14)
Caused by: java.lang.ClassNotFoundException: org.apache.jasper.JspC
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
… 1 more
java.lang.RuntimeException: Failed to compile jsp files via E:\Java\jdk1.6.0_13\
jre\bin\java.exe -classpath com.google.appengine.tools.development.LocalJspC -uriroot C:\DOCUME
~1\ADMINI~1\LOCALS~1\Temp\appcfg8338201102819535049.tmp -p org.apache.jsp -l -v
-webinc C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\appcfg8338201102819535049.tmp\WEB-INF
\generated_web.xml -d C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\appcfg83382011028195350
49.tmp\WEB-INF\classes

2.将jasper-compiler-5.0.28.jar.bak重命名回 jasper-compiler-5.0.28.jar,
将E:\Java\jdk1.6.0_13\bin\javac.exe重命名为 javacc.exe,
在Eclipse里通过Google app Engine的插件发布,得到下面的出错信息:

Unable to upload:
java.lang.IllegalStateException: cannot find javac executable based on java.home, tried “E:\Java\jdk1.6.0_13\jre\bin\javac.exe” and “E:\Java\jdk1.6.0_13\bin\javac.exe”
at com.google.appengine.tools.admin.AppAdminFactory$ApplicationProcessingOptions.getJavaCompiler(AppAdminFactory.java:325)
at com.google.appengine.tools.admin.Application.compileJavaFiles(Application.java:340)
at com.google.appengine.tools.admin.Application.compileJsps(Application.java:326)
at com.google.appengine.tools.admin.Application.createStagingDirectory(Application.java:235)
at com.google.appengine.tools.admin.AppAdminImpl.update(AppAdminImpl.java:39)
at com.google.appengine.eclipse.core.proxy.AppEngineBridgeImpl.deploy(AppEngineBridgeImpl.java:203)
at com.google.appengine.eclipse.core.deploy.DeployProjectJob.runInWorkspace(DeployProjectJob.java:97)
at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:38)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)
java.lang.IllegalStateException: cannot find javac executable based on java.home, tried “E:\Java\jdk1.6.0_13\jre\bin\javac.exe” and “E:\Java\jdk1.6.0_13\bin\javac.exe”
于是根据堆栈找到了com.google.appengine.tools.admin.Application,使用Jd-gui(来自http://java.decompiler.free.fr/)打开class找到了如下代码:
[code]
String javacCmd = opts.getJavaCompiler().getPath();
args.add(javacCmd);
args.add(“-classpath”);
args.add(classpath.toString());
args.add(“-d”);
args.add(classDir.getPath());

for (File f : new FileIterator(classDir)) {
if (f.getPath().toLowerCase().endsWith(“.java”))
args.add(f.getPath());

}

if (args.size() == 5)
return;

Process javac = startProcess((String[])args.toArray(new String[0]));
[/code]

从代码看到,Google App engine只用 apache Tomcat jasper生成java文件,再通过拼凑命令行字符串方式生成编译java文件为Class的命令,通过Process执行。
由于命令行参数没有设置encoding参数,于是javac使用了系统默认的file.,在中文Windows下,基本都是GBK。在Linux下,因为一般都是LANG=zh_CN.UTF-8,因此就不会遇到这个问题了。
下面是linux 下ps看到的完整javac命令:

lizongbo  6733  0.0  0.4 690156  9228 ?        Sl   21:16   0:00 /usr/local/jdk1.6.0_12/bin/javac -classpath /usr/local/java/appengine-java-sdk-1.2.0/lib/impl/appengine-api.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/impl/appengine-api-stubs.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/impl/appengine-local-runtime.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/geronimo-el_1.0_spec-1.0.1.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/geronimo-servlet_2.5_spec-1.2.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/appengine-local-runtime-shared.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/geronimo-jsp_2.1_spec-1.0.1.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/jsp/jasper-runtime-5.0.28.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/jsp/commons-el-1.0.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/jsp/ant-launcher-1.6.5.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/jsp/commons-logging-1.1.1.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/jsp/ant-1.6.5.jar:/usr/local/java/appengine-java-sdk-1.2.0/lib/shared/jsp/jasper-compiler-5.0.28.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/classes:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/ant-launcher-1.6.5.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/jakarta-standard-1.1.2.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/jasper-compiler-5.0.28.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/datanucleus-appengine-1.0.0.final.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/ant-1.6.5.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/datanucleus-core-1.1.0.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/geronimo-jta_1.1_spec-1.1.1.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/jdo2-api-2.3-SNAPSHOT.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/jasper-runtime-5.0.28.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/commons-logging-1.1.1.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/appengine-api-1.0-sdk-1.2.0.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/geronimo-jpa_3.0_spec-1.1.1.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/datanucleus-jpa-1.1.0.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/commons-el-1.0.jar:/tmp/appcfg8102867646621343748.tmp/WEB-INF/lib/jakarta-jstl-1.1.2.jar: -d /tmp/appcfg8102867646621343748.tmp/WEB-INF/classes /tmp/appcfg8102867646621343748.tmp/WEB-INF/classes/org/apache/jsp/test_jsp.java /tmp/appcfg8102867646621343748.tmp/WEB-INF/classes/org/apache/jsp/p_jsp.java

在Google app Engine的java SDK没有完善之前,只有在Ubuntu下写jsp最方便不会出现中文乱码问题。
受网上文章相关文章的误导,花了不少时间去看 apache tomcat japser的代码,并尝试替换 jasper-compiler-5.0.28.jar为Apache tomcat 6.0.18的最新版本,结果发现乱码问题的原因根本不在哪里。

appengine_web.xml里可以配置:<property name=”file.encoding” value=”UTF-8″ />。但是也不能解决乱码问题。

2 Comments »

  1. Here is the latest utf-8 solutions for java, recommended reference.

    这是针对JAVA最新的UTF-8解决方案,推荐参考

    http://www.jxva.com/blog/java-technologes/some-suggestions-to-improve-performance-about-java.html

    Reply

    评论 by jxva — 2009年04月15日 @ 00:17

  2. 上面发错了,应该是这篇
    Here is the latest utf-8 solutions for java, recommended reference.

    这是针对JAVA最新的UTF-8解决方案,推荐参考

    http://www.jxva.com/blog/personal-diary/change-the-google-app-engine's-javac-compiler-encoding.html

    Reply

    评论 by jxva — 2009年04月15日 @ 00:21

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress