Say I have jar file jarA and jarB.
class A is in jarA:
class A {
public static final String SQL = "select `col1`, `col2`, ... `col50` from `table`";
}
class B is in 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
}
}
When I run (and later debug) jarB with jarA in the class path, weird thing happened:
the sql executed was missing col25, it was like select col1, col2, ..., col24, col26, ..., col50 from ...
when I debug it, paused somewhere before the executeSQL(sql) thing, I ran some expressions below:
A.SQL returns the correct string(with col25)
a.SQL also returns correctly
sql is almost correct except that col25 is not there
I added -verbose:class at startup, I can see that class A was indeed loaded from jarA. Then I unzipped jarA, found A.class, reverse engineered it, I can see the string SQL is correct.
I know there's definitely something wrong. But any suggestions where I should look into, or any wild guesses?
SQL is a compile-time constant. That means that, when compiling the class B, the A.SQL string value will be inlined in B's byte-code.
So, my guess is that col25 was missing in A.SQL, B was compiled against this incorrect class, then A.SQL was fixed and recompiled, but B was not recompiled. So its bytecode still contains the incorrect sql string.
Recompile B, or, if SQL is not actually a constant (i.e. a value that will never, ever, ever change), then don't expose it as a public constant. Instead, define a method returning the SQL string, and use that method from the B class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With