4

I have an OSGi bundle b1 exporting a class with

public static final String MYVAL = "a"; //version 1

and a second bundle b2 is compiled and deployed using version 1 of b1.

Later on I change the value in b1 to

public static final String MYVAL = "b"; //version 2

but I only recompile and deploy b1, b2 is unchanged and not recompiled.

Is it possible that the b2 still sees value a at runtime?

palacsint
  • 28,416
  • 10
  • 82
  • 109
Leen Toelen
  • 389
  • 6
  • 12

1 Answers1

8

The value of a referenced static final primitive or string is directly inlined into the using class. So unrelated to OSGI and any visibility rules, b2 will still contain an embedded MYVAL value of "a".

I think this is documented in the Java Language Specification, Section 13.4:

If a field is a constant variable (§4.12.4), then deleting the keyword final or changing its value will not break compatibility with pre-existing binaries by causing them not to run, but they will not see any new value for the usage of the field unless they are recompiled. This is true even if the usage itself is not a compile-time constant expression (§15.28).

This answer to a similar question shows a workaround. Changing the declaration so it is no longer a constant expression disables this inlining behaviour.

public static final String MYVAL = String.valueOf("a");
Community
  • 1
  • 1
Jörn Horstmann
  • 33,639
  • 11
  • 75
  • 118
  • 1
    You should be able to avoid the new String object and use the interned "a" with: `public static final String MYVAL; { MYVAL = "a"; }` – BJ Hargrave May 10 '12 at 15:33
  • @BJHargrave: `valueOf` delegates to `toString` which will in fact return the same interned instance. I used `valueOf` to be consistent when creating a numeric constant as in `Integer.valueOf(1)`. – Jörn Horstmann May 10 '12 at 15:39
  • 1
    True, but valueOf is a method which must be executed while ```= "a"``` is an assignment to a string in the constant pool. – BJ Hargrave May 11 '12 at 15:55