今天在修改现场项目时,遇见一个特别值得深刻记住的问题,说大也不大,其实就是class常量池的问题。
场景是这样的,现场原来已经部署了一套软件,现在呢,软件有了一点问题,于是我在本地源代码里面添加了几行日志后,编译成class文件后,替换现场的class文件,重启现场的程序后,发现问题更严重了,直接报文件找不到异常,试了好多次都不行。
于是,我在多处添加日志,发现在日志里面打印的文件路径竟然是我本机那个文件的路径,我惊呆了 ,怎么会这样呢,后来经过分析,发现问题竟然出现在我的一个不经心的失误造成的。
原来造成这个原因是这样的,我在本地挑代码的时候,为了方便,在工具类中把一个静态变量的值直接改为一个我本机的决定路径(原来是通过设定系统变量得到的),但是呢,在我上面说的我要加日志的java文件中又引用了这个工具类中的变量。说到这,如果了解class文件格式的人应该能知道原因了。
下面我还是详细说一下其中的原理吧。在我改工具类中变量值之前,当编译java源文件的时候,编译器不知道这个变量到底是什么值,于是,在class中保持对原变量的引用,所以现场不会出问题。而当我把工具类中的变量改为绝对值时,这个时候,当编译器再次去编译文件时,发现在这个变量值已经定了,不会改了,所以在别的类中引用到这个变量值的时候,直接在class文件中替换成了一个绝对值,放在当前class文件中的常量池中。因为我是在本地编译的(值已经固定到class文件中了,即不再引用工具类中的变量),所以把class文件放到现场时,就出差了(现场的那个文件的路径和我本机路径不一样啊)。
哎哎,值得发表一篇文章来记住我这个一不小心造成的小错误啊-真是读书百遍,不如一次实战!