Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm new to Java and I saw a Q&A section here with two examples where mutability is removed. Upon testing MutableString.java:

import java.lang.reflect.Field; 

public class MutableString {

    public static void main(String[] args) { 
        String s = "Immutable"; 
        String t = "Notreally"; 

        mutate(s, t);
        StdOut.println(t); 

        // strings are interned so this doesn't even print "Immutable" (!)
        StdOut.println("Immutable");
    } 

    // change the first min(|s|, |t|) characters of s to t
    public static void mutate(String s, String t) {
        try {
            Field val = String.class.getDeclaredField("value"); 
            Field off = String.class.getDeclaredField("offset"); 
            val.setAccessible(true); 
            off.setAccessible(true); 
            int offset   = off.getInt(s); 
            char[] value = (char[]) val.get(s); 
            for (int i = 0; i < Math.min(s.length(), t.length()); i++)
                value[offset + i] = t.charAt(i); 
        } 
        catch (Exception e) { e.printStackTrace(); }
    } 

} 

I received the following error:

java.lang.NoSuchFieldException: offset

Any input on the following would be greatly appreciated:

a) why do I get this exception
b) how do I check which fields exist in a class (Java strings specifically)

share|improve this question
 
There is no field offset in the class String... –  LaurentG Jul 5 '13 at 12:58
2  
That is such a disgusting way to do things -.- –  luk2302 Jul 5 '13 at 13:00
4  
@LaurentG: there used to be one in Java 6 (or at least in the Oracle/Sun/OpenJDK implementation). Of course it was never documented, so depending on it was obviously a bug. –  Joachim Sauer Jul 5 '13 at 13:02
add comment

1 Answer

up vote 9 down vote accepted

Disclaimer: these kinds of hacks are interesting lessons in learning and fun trivia. But they are definitely not something that you want to use in any production code. It will lead to pain.

By their very nature, such a hack always depends on implementation details of the classes that are hacked.

In your case you seem to be using a String implementation that doesn't have an offset field, but uses some other mechanism (or maybe just a different name!).

For example, I've just reviewed the Oracle Java 7 String class and it no longer has the offset field (which was used in Java 6 and earlier to share the char[] among substrings)!*

You can use Class.getDeclaredFields() to check which fields this implementation does define:

for (Field f : String.class.getDeclaredFields()) {
  System.out.println(f);
}

For a version of that hack that works with Java 7, you could do this:

public static void mutate(String s, String t) {
    try {
        Field val = String.class.getDeclaredField("value"); 
        val.setAccessible(true); 
        char[] value = (char[]) val.get(s); 
        for (int i = 0; i < Math.min(s.length(), t.length()); i++)
            value[i] = t.charAt(i); 
    } 
    catch (Exception e) { e.printStackTrace(); }
} 

Of course, this too will break if the internals of String change again.

* Here's an Email that talks about that change, it seems that the sharing of the char[] only lead to improved performance in a few, special cases.

share|improve this answer
 
Thank you. I also got my starters +15 reputation so I can finally upvote good responses. –  ofer.sheffer Jul 5 '13 at 13:15
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.