Can you detect if a class is mutable ?

T

tomjbr.10216233

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
 
T

Thomas Hawtin

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
 
P

Patricia Shanahan

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
 
C

Chris Uppal

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
 
R

Roedy Green

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.
 
G

googmeister

Roedy said:
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.
 
G

googmeister

Chris said:
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

Ingo R. Homann

Hi googmeister,

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;
}
}
 
C

Chris Uppal

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
 
G

googmeister

Ingo said:
Hi googmeister,



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.
 
G

googmeister

Chris said:
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.
 
J

jan V

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,.. ;-)
 
J

jan V

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?
 
R

Robert Klemme

jan said:
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
 
I

Ingo R. Homann

Hi,

Robert said:
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
 
R

Robert Klemme

Ingo said:
Hi,



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
 
T

tomjbr.10216233

Is it even possible to correctly implement a method with the signature
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)"
}
}
 
T

tomjbr.10216233

Assuming for a second that this a method which you would actually
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
 
O

Oliver Wong

jan V said:
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
 
I

Ingo R. Homann

Hi,

Robert said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top