论坛首页 Java版

ddd

浏览 11365 次
锁定老贴子 主题: ddd
该帖已经被评为精华帖
作者 正文
时间:2007-05-30 关键字: ddd

                                   

   
时间:2007-05-31

zhh2007 写道:
另外,可惜的是javac1.7(包括sun公司以往发行的JDK中内置的javac)不是
一个优化编译器,javac1.7并没有独立的优化阶段,
散落在其他阶段的“优化”可以省略不计。

比如:(例子不考虑人的因素,只考虑编译器的行为):

java 代码
  1. package my.test;   
  2. public class Test {   
  3.     Test() {   
  4.         int v1=1;   
  5.         while(v1<10000) {   
  6.             int v2=5;   
  7.             v1=v1+v2*2;   
  8.         }   
  9.     }   
  10. }  

用javac1.7或JDK1.6.0生成的字节码如下(部分内容)
(用命令行“javap -verbose my.test.Test”查看):
---------------------------------------------------
my.test.Test();
  Code:
   Stack=3, Locals=3, Args_size=1
   0: aload_0
   1: invokespecial #1; //Method java/lang/Object."":()V
   4: iconst_1  //将常量1压入堆栈
   5: istore_1  //将常量1弹出堆栈并存入局部变量v1,
   6: iload_1   //将局部变量v1的值压入堆栈
   7: sipush 10000   //将常量10000压入堆栈
   10: if_icmpge 24  //弹出常量10000,弹出局部变量v1的值,局部变量v1的值>=10000结束循环
   13: iconst_5  //将常量5压入堆栈
   14: istore_2  //将常量5弹出堆栈并存入局部变量v2,
   15: iload_1   //将局部变量v1的值压入堆栈
   16: iload_2   //将局部变量v2的值压入堆栈
   17: iconst_2  //将常量2压入堆栈
   18: imul      //弹出常量2,弹出局部变量v2的值,相乘后将结果压入堆栈
   19: iadd      //弹出结果,弹出局部变量v1的值,相加后将结果压入堆栈
   20: istore_1  //弹出结果并存入局部变量v1
   21: goto 6 //转到6: iload_1
   24: return
---------------------------------------------------

理想的优化编译器应该能生成如下类似的代码:

java 代码
  1. package my.test;   
  2. public class Test {   
  3.     Test() {   
  4.         int v1=1;   
  5.         while(v1<10000) {   
  6.             v1=v1+10;//v2=5与v2*2总是不变的,可以合并成10   
  7.         }   
  8.     }   
  9. }  


更理想的优化编译器应该能生成如下类似的代码:

java 代码
  1. package my.test;   
  2. public class Test {   
  3.     Test() {}//局部变量v1没有任何用处,完全可以删除   
  4. }  
这个优化应该在JIT阶段会执行的吧.
   
0 请登录后投票
时间:2007-06-01
还记得递归下降算法、运算符优先这些名词,不过其原理还是要复习的。不过耐心却是个问题! 顶lz,感觉lz挺牛。
   
0 请登录后投票
时间:2007-06-01
zhh2007 写道
我只说说我采用的方法(我是第一次分析别人的源代码):
1) 找到一种最简单的办法完成源代码的第一次编译
2) 找到第一个开始运行的类文件(也就是找到切入点)
3) 粗略看一下这个类文件定义了哪些字段,有构造方法的话,
粗略看一下构造方法中做了哪些初始化工作
4) 要是定义的字段、构造方法太多,把它们都copy一份,单独放到一个文件

5) 找到第一个被运行的方法,
在方法开头和末尾打上Debug(包装System.out.println()后写成的一个类),
觉得关键的字段(或局部变量),用自己喜欢的方式也打上Debug,
如果类文件源码超过200行(javac1.7源码中有许多核心类文件大多超过1000行),
为了切换方便,把这方法copy一份,单独放到一个文件

6) 当在一个方法中调用了另一个类的方法时,转到3)
7) 当一个类文件中定义的方法有85%都已Debug过了,从头到尾细细分析一遍类文件
8) Debug的输出信息最好重定向到一个自定义的文件
9) 方法中有复杂算法时最好用笔画在纸上

10)有很多个方法同时来回调用时,把每个方法按调用的顺序单独打开,对照Debug
信息一起看(我经常打开5、6个EditPlus窗口实例同时看20几个类文件)

11)记住随心所欲地想把一个个类文件不打Debug、不按流程顺序分析,是非常低效
的一种方法,除非这个类文件很独立,只是简单的字段值存取功能。


这么看太麻烦了,建议下个source insight,看代码很方便
听说idea用来看代码也不错
   
0 请登录后投票
时间:2007-06-01
把看代码的方法也写出来,楼主相当不错。

如果不是工作需要,我真是没有动力去看大量的源代码。 兴趣有,就是没有耐心
   
0 请登录后投票
时间:2007-06-02
因为工作与兴趣不同,除非工作上需要,学习这些底层的东西基本上没有用,不如多学点工作上能用到的一些设计层面的东西。
不过这些基础还是要学习的,看看如何实现的~,but the work have the higher priority 。
   
0 请登录后投票
时间:2007-06-02
跟着兴趣走很好, 如果能在能养活自己的前提下,会走得很远.
   
0 请登录后投票
时间:2007-06-05
学编译原理的时候,还是补考刚刚过得呢,想来很难,有兴趣再拾来再温习一下,到了上班的时候,才觉得学的不是自己想要的了,
   
0 请登录后投票
时间:2007-06-05
xruby 项目正缺人手,贴主不妨试试看。
   
0 请登录后投票
时间:2007-06-06
我插一句关于优化, Java毕竟是个中级语言, 优化到无用代码都扔掉的份儿可能不太妥当, 不然Benchmarks都没法写了. 有些指令可能纯粹就是为了profiling, 看看执行效率如何.

另外SUN JDK javac的优化在所有编译器里应该算是最多的了. 至于没有专门的优化pass, 个人觉得是因为JVM指令已经很抽象了, 不像 CISC 指令集对同样的事情有那么多可互换的方案和不同处理器型号的专有指令, 放在其他pass里的一些优化感觉就是发现了潜在可能就做一下, 相对直观简单. 如果专门设立一个Java优化pass, 恐怕只能从整体到细微的执行patterns上全面判断了, 匹配条件可能也比较复杂. 目前JDK javac已经算是编译速度最慢的了, 再加入复杂匹配优化恐怕会被抱怨得更惨.

另外个人感觉OpenJDK Javac目前最大的开发焦点和亮点是增量编译, javavc一直以来基本作为命令行编译器的历史决定了它的增量编译能力到目前为止是个相当大的缺陷. 增量编译支持和编译器API接口直接决定了它用于Java IDE的价值, 对比一下NetBeans5.5和Eclipse的即时语法错误标示响应时间就很明显了. Java已经进入IDE时代了, 从SUN对NetBeans的投入可以看到其重要性. NetBeans 6 开发团队在javac基础上做了很多增强和改进, 让NB6的开发体验有了很大提升, 其中就包括增量编译支持和Compiler API. 这些改进正在逐步合并到OpenJDK中去, 研究的时候不妨也留意这个方面的东西.
   
0 请登录后投票
论坛首页 Java版

跳转论坛:
JavaEye推荐