说我有jar文件jarA
和jarB
.
class A
在jarA
:
class A { public static final String SQL = "select `col1`, `col2`, ... `col50` from `table`"; }
class B
在jarB
:
class B { public void loadData() { String sql = "some other sql"; ... A a = null; sql = a.SQL + " where something = something"; //This actually works, I never thought about it before I saw this code. executeSQL(sql); //jdbc stuff } }
当我在类路径中运行(以及稍后调试)jarB
时jarA
,发生了奇怪的事情:
执行的sql丢失了col25
,就像是select col1, col2, ..., col24, col26, ..., col50 from ...
当我调试它,在executeSQL(sql)
事情之前的某个地方暂停时,我在下面运行了一些表达式:
A.SQL
返回正确的字符串(with col25
)
a.SQL
也正确返回
sql
几乎是正确的,除非col25
那里没有
我-verbose:class
在启动时添加,我可以看到class A
确实是从中加载的jarA
.然后我解压缩jarA
,发现A.class
,逆向工程,我可以看到字符串SQL
是正确的.
我知道肯定有问题.但是我应该研究哪些建议,或者任何疯狂的猜测?
SQL是一个编译时常量.这意味着,在编译 B类时,A.SQL
字符串值将以B的字节码内联.
所以,我的猜测是在A.SQL中缺少col25,B是针对这个不正确的类编译的,然后A.SQL被修复并重新编译,但是B没有被重新编译.所以它的字节码仍然包含不正确的sql字符串.
重新编译B,或者,如果SQL实际上不是常量(即永远不会改变的值),则不要将其公开为公共常量.相反,定义一个返回SQL字符串的方法,并使用B类中的该方法.