1

I'm seeing some very strange behavior in a java program. The failure is not reproducible, so all I have to go on is the original logs.

The class looks something like this:

public class MyClass {
    public static final String MY_CONSTANT_STRING = "This should never change";

    public boolean checkEndsWithCS(String inString) {
        return inString.endsWith(MY_CONSTANT_STRING);
    }

    public String getString() {
        return "Some text '" + MY_CONSTANT_STRING + "' some more text";
    }
}

In the logs, I see a case where getString returns "Some text '' some more text" and checkEndsWithCS("These are not the chars you're looking for.") returns true.

I can only conclude that MY_CONSTANT_STRING is "" in this case.

No other class extends MyClass, so it's not getting overridden in a higher level class.

I don't see any sign of an out of memory condition in the log, which would seem like the most likely cause.

It's static final, so the reference shouldn't change. Strings are immutable, so the string shouldn't change.

Questions:

  1. When do these execute? I set a breakpoint in eclipse, and it never gets hit.
  2. Is there any possible way for an immutable string in a static final reference to change?
  3. Is there any possible way for the string not to get assigned in the first place?
  4. Is there any way the memory containing the string or reference could be getting "clobbered" by some other object or process?
  5. Any other subtle gotchas where I'm just not thinking about this the right way?

If the collective experience here can't break this loose, then I'll just take it as a sign that my data are faulty and examine it from that angle.

14
  • 1
    Can you show the code accessing MyClass.MY_CONSTANT_STRING? Commented Feb 5, 2013 at 8:32
  • I am not sure, but referencing it in static initialization block could be a problem. Commented Feb 5, 2013 at 8:32
  • 7
    @tbroberg Usually it's something silly, like you have another constant named MY_CONSTANT_STRING different from MyClass.MY_CONSTANT_STRING and you are mixing them up in your code. Worth double checking IMO Commented Feb 5, 2013 at 8:36
  • 9
    If you compile a class when the String was "" and recompile the MyClass but not the class which uses it, you many not see the change. This is because the compiler will in line constants such as String. Commented Feb 5, 2013 at 8:37
  • 1
    @tbroberg: Do you have any static imports? Have you tried cleaning your project? Does a breakpoint at getString() trigger? If yes, you can check the contents of MY_CONSTANT_STRING there. If no, you're not calling that method. Commented Feb 5, 2013 at 8:46

2 Answers 2

3

It is possible to use Java reflection to change the values of final fields, or mess around with the private fields of a String object.

It is also possible for native code (e.g. native methods) to overwrite memory, and that could potentially lead to some String object's length changing to zero.

If something in your code-base is doing this kind of stuff, it is going to be difficult to identify the culprit. And you shouldn't entirely overlook possibilities like:

  • some third party library doing it,
  • some non-trusted code doing it (if you are running non-trusted code without a sandbox),
  • something exploiting a known security flaw ... 'cos you haven't been keeping up to date with your patching,
  • something (or someone) interfering with the log file.

Or you might not be running code that matches the source code that you are looking at.


1) When do these execute? I set a breakpoint in eclipse, and it never gets hit. I put a breakpoint on the assignment of MY_CONSTANT_STRING ...

That code gets executed as part of the static initialization of the class. Maybe it was executed before you set the breakpoint. Or maybe there is a bug in the debugger.

2) Is there any possible way for an immutable string in a static final reference to change?

Yes. See above.

3) Is there any possible way for the string not to get assigned in the first place?

Given just your code as written here, No. However, if you have a cycle in the static initialization graph, it is possible to see the value of MY_CONSTANT_STRING before it has been assigned. However, that value will be null ... not an empty string.

4) Is there any way the memory containing the string or reference could be getting "clobbered" by some other object or process?

Yes. See above.

5) Any other subtle gotchas where I'm just not thinking about this the right way?

Possibly. I can't read your mind from this distance :-)

Sign up to request clarification or add additional context in comments.

Comments

2

Almost surely, either:

  1. This is not the actual code you're executing, and your real code does something meaningfully different which explains the difference. Ask your IDE to take you to the declaration of this constant where it is used. It may not be what you think.
  2. This is your source code, but the compiled code is not up to date. It looks like you're executing / not executing code that you're not / are
  3. You are not actually calling this class

static assignments and initializers happen when the class is initialized, before any methods of the class are called or instances created. This is guaranteed. String is immutable, and final references do not change after assignment. You can't override fields, ever, and can't override anything static, ever. (Though you can hide them for sure.)

The only other value you could possibly observe for this field is null, which would happen if it is final but you reference it in a static block before it is assigned -- which is hard to do, can only happen in a sort of circular initialization scenario.

Barring a JVM bug -- and, this is not utterly impossible -- no a reference can't be corrupted by any action of Java code.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.