class常量池陷阱-百看不如一战
2014-04-24 19:54
253 查看
今天在修改现场项目时,遇见一个特别值得深刻记住的问题,说大也不大,其实就是class常量池的问题。
场景是这样的,现场原来已经部署了一套软件,现在呢,软件有了一点问题,于是我在本地源代码里面添加了几行日志后,编译成class文件后,替换现场的class文件,重启现场的程序后,发现问题更严重了,直接报文件找不到异常,试了好多次都不行。
于是,我在多处添加日志,发现在日志里面打印的文件路径竟然是我本机那个文件的路径,我惊呆了 ,怎么会这样呢,后来经过分析,发现问题竟然出现在我的一个不经心的失误造成的。
原来造成这个原因是这样的,我在本地挑代码的时候,为了方便,在工具类中把一个静态变量的值直接改为一个我本机的决定路径(原来是通过设定系统变量得到的),但是呢,在我上面说的我要加日志的java文件中又引用了这个工具类中的变量。说到这,如果了解class文件格式的人应该能知道原因了。
下面我还是详细说一下其中的原理吧。在我改工具类中变量值之前,当编译java源文件的时候,编译器不知道这个变量到底是什么值,于是,在class中保持对原变量的引用,所以现场不会出问题。而当我把工具类中的变量改为绝对值时,这个时候,当编译器再次去编译文件时,发现在这个变量值已经定了,不会改了,所以在别的类中引用到这个变量值的时候,直接在class文件中替换成了一个绝对值,放在当前class文件中的常量池中。因为我是在本地编译的(值已经固定到class文件中了,即不再引用工具类中的变量),所以把class文件放到现场时,就出差了(现场的那个文件的路径和我本机路径不一样啊)。
哎哎,值得发表一篇文章来记住我这个一不小心造成的小错误啊-真是读书百遍,不如一次实战!
场景是这样的,现场原来已经部署了一套软件,现在呢,软件有了一点问题,于是我在本地源代码里面添加了几行日志后,编译成class文件后,替换现场的class文件,重启现场的程序后,发现问题更严重了,直接报文件找不到异常,试了好多次都不行。
于是,我在多处添加日志,发现在日志里面打印的文件路径竟然是我本机那个文件的路径,我惊呆了 ,怎么会这样呢,后来经过分析,发现问题竟然出现在我的一个不经心的失误造成的。
原来造成这个原因是这样的,我在本地挑代码的时候,为了方便,在工具类中把一个静态变量的值直接改为一个我本机的决定路径(原来是通过设定系统变量得到的),但是呢,在我上面说的我要加日志的java文件中又引用了这个工具类中的变量。说到这,如果了解class文件格式的人应该能知道原因了。
下面我还是详细说一下其中的原理吧。在我改工具类中变量值之前,当编译java源文件的时候,编译器不知道这个变量到底是什么值,于是,在class中保持对原变量的引用,所以现场不会出问题。而当我把工具类中的变量改为绝对值时,这个时候,当编译器再次去编译文件时,发现在这个变量值已经定了,不会改了,所以在别的类中引用到这个变量值的时候,直接在class文件中替换成了一个绝对值,放在当前class文件中的常量池中。因为我是在本地编译的(值已经固定到class文件中了,即不再引用工具类中的变量),所以把class文件放到现场时,就出差了(现场的那个文件的路径和我本机路径不一样啊)。
哎哎,值得发表一篇文章来记住我这个一不小心造成的小错误啊-真是读书百遍,不如一次实战!
相关文章推荐
- 好记性不如烂笔头102-spring3(22)-高并发下的延迟加载陷阱
- 委托异步调用时BeginInvoke的陷阱处理
- C/C++ typedef 陷阱
- 算法竞赛入门经典 浮点数陷阱
- JAVA重载(overload)和覆盖(override)中你所不知道的陷阱
- python循环删除的陷阱
- C++陷阱系列(1):让面试官倒掉的题
- 狗屎不如的4小时
- Unity3D 运营商支付 安卓打包的陷阱 libunicomsdk.jar
- Linux应用环境实战07:硬盘分区的陷阱及应对
- 谋哥:行万里路不如名师指路
- 考研路上的那些一战二战三战成功与失败的故事系列之三
- 考研路上的那些一战二战三战成功与失败的故事系列之十九
- python 可变参数的一个陷阱
- javascript this指针的陷阱
- WinForm相对路径的陷阱
- 递归的陷阱
- Java super.getClass() 陷阱