Can you detect if a class is mutable ?

Discussion in 'Java' started by tomjbr.10216233@bloglines.com, Aug 15, 2005.

  1. Guest

    Is it even possible to correctly implement a method with the signature
    below ?
    "public static boolean isMutable(Class c)"

    This method should be able to use reflection to detect if an arbitrary
    class is mutable, i.e. if the fields in the class are ever changed
    outside of the constructor.

    I know that you can quite easily programmatically detect if all the
    fields are final and if so, you can jump to the conclusion that the
    class is immutable, but a class could of course be immutable even if
    the fields are not declared as final.

    I think Aspect-Oriented Programming (AOP) could be used to
    programmatically detect when a field _is_ changed, but the question
    here is whether it is possible to detect that a field _can_ be changed.

    If it is actually possible, maybe there exists an open source class
    with an implementation of the method I am looking for ?

    / Tom
    , Aug 15, 2005
    #1
    1. Advertising

  2. wrote:
    > Is it even possible to correctly implement a method with the signature
    > below ?
    > "public static boolean isMutable(Class c)"
    >
    > This method should be able to use reflection to detect if an arbitrary
    > class is mutable, i.e. if the fields in the class are ever changed
    > outside of the constructor.
    >
    > I know that you can quite easily programmatically detect if all the
    > fields are final and if so, you can jump to the conclusion that the
    > class is immutable, but a class could of course be immutable even if
    > the fields are not declared as final.


    You can install a javaagent that examines the byte code using
    java.lang.instrument. Or you could make assumptions about the class
    loader and try to read the .class file.

    However, the analysis as to whether it is an immutable class is more
    complex.

    The String class writes to one of its fields to cache hash codes, but
    it's still immutable Hence mutable in C++.

    A class could have a final List, say, and still mutate the list. Hence
    the meaning of const isn't as useful as it might be.

    A class even without fields can have state, through it's identity
    (external attributes), synchronisation, finalisation and interaction
    with References.

    A synthetic class can also mutate final fields.

    Tom Hawtin
    --
    Unemployed English Java programmer
    http://jroller.com/page/tackline/
    Thomas Hawtin, Aug 15, 2005
    #2
    1. Advertising

  3. wrote:
    > Is it even possible to correctly implement a method with the signature
    > below ?
    > "public static boolean isMutable(Class c)"
    >
    > This method should be able to use reflection to detect if an arbitrary
    > class is mutable, i.e. if the fields in the class are ever changed
    > outside of the constructor.


    If you assume unbounded memory, it is provably impossible.

    One could wrap a simulation of an arbitrary Turing machine computation M
    in a method within a class C that modifies one of C's fields if, and
    only if, M halts. In effect, one could use isMutable(C) to construct a
    decider for the Turing machine halting problem.

    See http://en.wikipedia.org/wiki/Halting_problem

    Patricia
    Patricia Shanahan, Aug 15, 2005
    #3
  4. Chris Uppal Guest

    wrote:
    > Is it even possible to correctly implement a method with the signature
    > below ?
    > "public static boolean isMutable(Class c)"
    >
    > This method should be able to use reflection to detect if an arbitrary
    > class is mutable, i.e. if the fields in the class are ever changed
    > outside of the constructor.


    This cannot be done using reflection. Not enough information is available by
    that route.

    If you (taking Patricia's and Thomas's points into account), rephrase the
    question as "is it possible to tell whether a class includes code, outside the
    constructors, which if executed would change the value of any of its fields",
    then that can be done quite straightforwardly by bytecode inspection, but not
    by any pre-packaged "higher level" means.

    -- chris
    Chris Uppal, Aug 15, 2005
    #4
  5. Roedy Green Guest

    On Mon, 15 Aug 2005 01:57:52 GMT, Patricia Shanahan <>
    wrote or quoted :

    >If you assume unbounded memory, it is provably impossible.


    Whether the program ever changes the object is a much tougher problem
    than does the program contain code that changes instance variables of
    a particular class. Examine the class files. You would have to
    change a chain of dependencies of all methods called by any instance
    method of the class to look for putfield and similar instructions. To
    be thorough, you also have to track any classes loaded dynamically.

    Just examining a single class you could in some cases tell it was
    definitely immutable -- all private final variables.
    Roedy Green, Aug 15, 2005
    #5
  6. Guest

    Roedy Green wrote:
    >
    > Just examining a single class you could in some cases tell it was
    > definitely immutable -- all private final variables.


    I don't see why this is enough to guarantee immutability. If one
    of the instance variables is a private final array, you can still
    change the array elements, ruining immutability.
    , Aug 15, 2005
    #6
  7. Guest

    Chris Uppal wrote:
    >
    > If you (taking Patricia's and Thomas's points into account), rephrase the
    > question as "is it possible to tell whether a class includes code, outside the
    > constructors, which if executed would change the value of any of its fields",
    > then that can be done quite straightforwardly by bytecode inspection, but not
    > by any pre-packaged "higher level" means.


    I think Patricia's point was that the problem is undecidable. I must be
    missing something because it sounds like you are claiming that you
    can somehow solve the halting problem by checking bytecode.
    , Aug 15, 2005
    #7
  8. Hi googmeister,

    wrote:
    > Chris Uppal wrote:
    >
    >>If you (taking Patricia's and Thomas's points into account), rephrase the
    >>question as "is it possible to tell whether a class includes code, outside the
    >>constructors, which if executed would change the value of any of its fields",
    >>then that can be done quite straightforwardly by bytecode inspection, but not
    >>by any pre-packaged "higher level" means.

    >
    > I think Patricia's point was that the problem is undecidable. I must be
    > missing something because it sounds like you are claiming that you
    > can somehow solve the halting problem by checking bytecode.


    I think, the question is how you define "immutable". This seems quite a
    simple question, but is indeed a difficult definition, I think:

    (A) a class is immutable, if non of its members can change ("shallow
    immutability")
    (B) a class is immutable, if non of its memebs can change and every
    referenced object itself is immutable using this definition ("deep
    immutability"). Note that an array is not immutable.
    (C) a class is immutable, if every of its method (academic question:
    even private methods that are never called?) always returns the same
    value (perhaps something like "runtime immutability" although this is a
    strage phrase)

    Considering (A) and (B), the halting problem is not to be solved:

    If a class has some kind of setter-method, then it is mutable.
    If a class has a method to get a reference to an embedded object/member
    that is mutable (including arrays), then the class is itself mutable.
    If the class has a constructor that assignes a mutable object to a
    member, then the class is mutable.
    If ...
    If none of the above is the case, then the class is immutable.

    This can be done quite "simple" by byte code analysis. (Hint: mark all
    members as final and see if there is a compiler-error. Do the same for
    every referenced class.)

    Anyway, there are very few classes that are really immutable with this
    definition, I think!

    Note also that I do not cosider changing the value of a class using
    reflection or some JNI-calls.

    Ciao,
    Ingo

    Perhaps some interesting cases:

    class Immutable {
    public int getValue() {
    return Math.nextRandom();
    }
    }

    class Immutable {
    private int getValue() {
    return Math.nextRandom();
    }
    }

    class Mutable {
    int i=0;
    public int getValue() {
    if(i==0) {
    i=42;
    }
    return i;
    }
    }
    Ingo R. Homann, Aug 15, 2005
    #8
  9. Chris Uppal Guest

    wrote:

    > > If you (taking Patricia's and Thomas's points into account), rephrase
    > > the question as "is it possible to tell whether a class includes code,
    > > outside the constructors, which if executed would change the value of
    > > any of its fields", [...].

    >
    > I think Patricia's point was that the problem is undecidable. I must be
    > missing something because it sounds like you are claiming that you
    > can somehow solve the halting problem by checking bytecode.


    Not at all ;-) The point of my rephrasing of the question was that it is
    straightforward to detect whether the class contains code that /if executed/
    will change some field's value. Determining -- in general -- whether that code
    /can/ ever be executed is slightly trickier...

    -- chris
    Chris Uppal, Aug 15, 2005
    #9
  10. Guest

    Ingo R. Homann wrote:
    > Hi googmeister,
    >
    > wrote:
    > > Chris Uppal wrote:
    > >
    > >>If you (taking Patricia's and Thomas's points into account), rephrase the
    > >>question as "is it possible to tell whether a class includes code, outside the
    > >>constructors, which if executed would change the value of any of its fields",
    > >>then that can be done quite straightforwardly by bytecode inspection, but not
    > >>by any pre-packaged "higher level" means.

    > >
    > > I think Patricia's point was that the problem is undecidable. I must be
    > > missing something because it sounds like you are claiming that you
    > > can somehow solve the halting problem by checking bytecode.

    >
    > I think, the question is how you define "immutable". This seems quite a
    > simple question, but is indeed a difficult definition, I think:
    >
    > (A) a class is immutable, if non of its members can change ("shallow
    > immutability")
    > (B) a class is immutable, if non of its memebs can change and every
    > referenced object itself is immutable using this definition ("deep
    > immutability"). Note that an array is not immutable.
    > (C) a class is immutable, if every of its method (academic question:
    > even private methods that are never called?) always returns the same
    > value (perhaps something like "runtime immutability" although this is a
    > strage phrase)
    >
    > Considering (A) and (B), the halting problem is not to be solved:
    >
    > If a class has some kind of setter-method, then it is mutable.
    > If a class has a method to get a reference to an embedded object/member
    > that is mutable (including arrays), then the class is itself mutable.
    > If the class has a constructor that assignes a mutable object to a
    > member, then the class is mutable.
    > If ...
    > If none of the above is the case, then the class is immutable.
    >
    > This can be done quite "simple" by byte code analysis. (Hint: mark all
    > members as final and see if there is a compiler-error. Do the same for
    > every referenced class.)
    >
    > Anyway, there are very few classes that are really immutable with this
    > definition, I think!


    Thanks for the explanation. I was going with definition (C). This seems
    to be the most useful definition and the one Java uses, e.g., as in
    Strings are immutable.
    , Aug 15, 2005
    #10
  11. Guest

    Chris Uppal wrote:
    > wrote:
    >
    > > > If you (taking Patricia's and Thomas's points into account), rephrase
    > > > the question as "is it possible to tell whether a class includes code,
    > > > outside the constructors, which if executed would change the value of
    > > > any of its fields", [...].

    > >
    > > I think Patricia's point was that the problem is undecidable. I must be
    > > missing something because it sounds like you are claiming that you
    > > can somehow solve the halting problem by checking bytecode.

    >
    > Not at all ;-) The point of my rephrasing of the question was that it is
    > straightforward to detect whether the class contains code that /if executed/
    > will change some field's value. Determining -- in general -- whether that code
    > /can/ ever be executed is slightly trickier...


    OK, I think I misunderstand your post - you are *changing* the
    question,
    not *rephrasing* it.

    Even with this change, the problem is still undecidable since you can't
    decide whether you are actually changing the value of a variable or
    overwriting it with the same value (thereby preserving immutability),
    But
    this is probably more of an academic quibble than a practical one.
    , Aug 15, 2005
    #11
  12. jan V Guest

    > OK, I think I misunderstand your post - you are *changing* the
    > question, not *rephrasing* it.


    Damn, now we need a program to test the equivalence of sentences... phew. I
    wonder if that can be written, or whether such an algorithm may need to run
    for ever... hmmmm,.. ;-)
    jan V, Aug 15, 2005
    #12
  13. jan V Guest

    > Is it even possible to correctly implement a method with the signature
    > below ?
    > "public static boolean isMutable(Class c)"


    Assuming for a second that this a method which you would actually want in a
    real system, can you enlighten us and explain why?
    jan V, Aug 15, 2005
    #13
  14. jan V wrote:
    >> Is it even possible to correctly implement a method with the
    >> signature below ?
    >> "public static boolean isMutable(Class c)"

    >
    > Assuming for a second that this a method which you would actually
    > want in a real system, can you enlighten us and explain why?


    Although not knowing the OP's intentions this property could be used for
    various optimizations - mainly deciding whether you need to copy instances
    or whether you can replace an instance by a globally stored unique
    representative (see String.intern() for example).

    Kind regards

    robert
    Robert Klemme, Aug 15, 2005
    #14
  15. Hi,

    Robert Klemme wrote:
    > Although not knowing the OP's intentions this property could be used for
    > various optimizations - mainly deciding whether you need to copy instances
    > or whether you can replace an instance by a globally stored unique
    > representative (see String.intern() for example).


    But you know that at compile time already! So you can use (marker-)
    interfaces for that.

    A "const" keyword (different to "final") would be more interesting, IMHO!

    Ciao,
    Ingo
    Ingo R. Homann, Aug 15, 2005
    #15
  16. Ingo R. Homann wrote:
    > Hi,
    >
    > Robert Klemme wrote:
    >> Although not knowing the OP's intentions this property could be used
    >> for various optimizations - mainly deciding whether you need to copy
    >> instances or whether you can replace an instance by a globally
    >> stored unique representative (see String.intern() for example).

    >
    > But you know that at compile time already! So you can use (marker-)
    > interfaces for that.


    Not necessarily: you cannot retrofit 3rd party and JRE classes to
    implement this interface. And sometimes you won't even know which classes
    you are going to see at runtime.

    > A "const" keyword (different to "final") would be more interesting,
    > IMHO!


    What kind of semantics do you want to attach to that keyword?

    Kind regards

    robert
    Robert Klemme, Aug 15, 2005
    #16
  17. Guest

    >> Is it even possible to correctly implement a method with the signature
    >> below ?
    >> "public static boolean isMutable(Class c)"


    >Assuming for a second that this a method which you would actually want in a
    >real system, can you enlighten us and explain why?



    Okay, I think it is easiest to explain with a code example:

    public interface MyInterface {
    int getValue();
    }

    public class ImmutableClass implements MyInterface {
    private int value;
    public ImmutableClass(int value)
    {
    this.value = value;
    }
    public int getValue() {
    return value;
    }
    }

    public class MutableClass implements MyInterface {
    private int value;
    public MutableClass(int value)
    {
    setValue(value);
    }
    public int getValue() {
    return value;
    }
    public void setValue(int value) {
    this.value = value;
    }
    }

    public class SomeClass {

    private MyInterface myInterface;

    public SomeClass(MyInterface myInterface) {
    if(isMutable(myInterface.getClass()))
    {
    // since the externally created object is mutable
    // we should not store a reference to the external object
    this.myInterface = getClone(myInterface);
    }
    else
    {
    // not necessary to do any slow cloning since it is immutable
    this.myInterface = myInterface;
    }
    }

    private boolean isMutable(Class c)
    {
    // How to implement this method ???
    return ...;
    }

    private MyInterface getClone(MyInterface myInterface)
    {
    // This method could for example be implemented
    //with this slow but generic serialization implementation:
    //http://www.javaworld.com/javaworld/javatips/jw-javatip76-p2.html
    return ...;
    }
    }

    public class Main {
    public static void main(String[] args) {

    MutableClass mutableObject = new MutableClass(1);
    SomeClass someObject1 = new SomeClass(mutableObject);
    mutableObject.setValue(5); // modifies internals of someObject1
    // To avoid this situation, you want the class "SomeClass"
    // constructor to copy the mutableObject
    // instead of storing a reference to it.


    ImmutableClass immutableObject = new ImmutableClass(1);
    SomeClass someObject2 = new SomeClass(immutableObject);
    // In this case, the code is safe, since immutableObject
    // can not be changed from the outside, and therefore
    // it would be a waste of performance to always clone
    // the objects in the constructor of "SomeClass".

    // That is the reason for why it could be useful to be able to
    // detect mutability in a method "isMutable(Class c)"
    }
    }
    , Aug 15, 2005
    #17
  18. Guest

    >> Assuming for a second that this a method which you would actually
    >> want in a real system, can you enlighten us and explain why?


    >Although not knowing the OP's intentions this property could be used for
    >various optimizations - mainly deciding whether you need to copy instances
    >or whether you can replace an instance by a globally stored unique
    >representative (see String.intern() for example).


    Yes, that was my intention, and in another posting in this thread I
    have submitted a code example that illustrates the situation.
    / Tom
    , Aug 15, 2005
    #18
  19. Oliver Wong Guest

    "jan V" <> wrote in message
    news:SB_Le.169840$-ops.be...
    >> OK, I think I misunderstand your post - you are *changing* the
    >> question, not *rephrasing* it.

    >
    > Damn, now we need a program to test the equivalence of sentences... phew.
    > I
    > wonder if that can be written, or whether such an algorithm may need to
    > run
    > for ever... hmmmm,.. ;-)


    If you had such a program, you could use it to solve the halting
    problem: i.e. test whether the "sentence" (which happens to be source code)
    is equivalent to this sentence: "while (true);"

    - Oliver
    Oliver Wong, Aug 15, 2005
    #19
  20. Hi,

    Robert Klemme wrote:
    >>A "const" keyword (different to "final") would be more interesting,
    >>IMHO!

    >
    > What kind of semantics do you want to attach to that keyword?


    Similar to C++: To mark an (otherwise mutable) parameter of a method for
    example, that it can *not* be modified, e.g.:

    public void foo(const StringBuffer sb) {
    System.out.println(sb.toString()); // OK
    sb.append("bar"); // compiler-error
    }

    This would be quite useful!

    (And, yes, I know that some effort will be necessary on the API and the
    JVM to achieve this, but it's not too difficult.)

    Ciao,
    Ingo
    Ingo R. Homann, Aug 16, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. hiwa
    Replies:
    4
    Views:
    479
    Oliver Wong
    Mar 8, 2006
  2. Matt MC
    Replies:
    13
    Views:
    5,058
  3. Adam H. Peterson

    mutable base class

    Adam H. Peterson, Apr 2, 2004, in forum: C++
    Replies:
    5
    Views:
    490
    Adam H. Peterson
    Apr 3, 2004
  4. Dan Perl
    Replies:
    52
    Views:
    1,199
    Andrew Dalke
    Sep 3, 2004
  5. Replies:
    6
    Views:
    276
Loading...

Share This Page