I am trying to apply the lessons from reading Java Concurrency In Practice with regards to declaring whether classes that I write are either thread-safe or that they contain unsynchronised mutable state. I think this is a good idea because it documents the intention of how the class should be used.
Today, I wrote a class which wraps an instance of java.lang.Class and java.net.URI. I was about to write in the javadoc that it is thread-safe immutable since both fields were declared as final references. However, I looked at the source code for URI and Class and didn't see any declaration of whether they are thread-safe and it didn't seem immediately obvious.
Thinking about this more generally: is there a list of common java classes stating whether they are thread-safe or not?
On the other had, it probably doesn't matter whether the instances are strictly thread-safe because of the way this class is being used, I will mark it as 'probably thread-safe' for now.
There is no definitive list of thread-safe classes in Java. The only people who could produce a definitive list would be Oracle1, and they haven't done so.
1 - Oracle is the custodian of both the reference Java class libraries (including javadocs), other "official" documentation and .. the official compliance test suite for Java. They are the people who would say whether a class (or subset of a class) that is thread-safe, is thread-safe by design, or whether it is merely a implementation artefact. Nobody else can make that calll with total certainty; i.e. whether a class that is thread-safe in the standard Oracle codebase should also be thread-safe in Harvest / Android codebase or the Classpath codebase, or ...
All immutable classes are assumed to be thread-safe. For mutable classes the common practice is to state explicitly when the class is thread-safe; if nothing is stated, you can't assume thread safety.
I have never heard of a list of thread-safe JDK classes, though.
All java.lang classes (As Marko said immutable classes are assumed to be thread-safe). Also BigDecimal and BigInteger and few more. Unfortunately there is no list of that classes.
If you need some thread-safe collections try Google Guava Immutable Collections (http://code.google.com/p/guava-libraries/wiki/GuavaExplained?tm=6)
Related
I made my class immutable by following all java standards
A. Defined class as final
B. declared all fields as private and final
C. No setter method
D. No method changes the state of object
E. declared all method as final
F. Safer/defencieve copying of collection/ non mutable object fields.
These are the priliminary checkpoints I made when desigining immutable class.
But one question left, my object can still be modified by java reflection, am I right?
Or is there any point I missed in the class?
Thanks in advance.
There's no hiding from reflection - even immutable classes are not immune. There is nothing you can do about it, though, so "cannot be modified through reflection" is not one of the criteria of immutability.
Yes. Reflection can still access / change it. You can't really plan against that. If someone's altering your object with reflection, I would doubt the quality of code they're writing.
Immutable classes are fantastic to ensure thread safe applications. Immutable objects are ALWAYS thread safe. If you're looking for more great information, please read Effective Java. It's a MUST READ for any Java developer.
Yes, still it can be modified through reflection. Apart from that it seems you took required care to make it immutable.
I know of at least 2 mechanisms to enforce that a Collection should not be modified:
Java's unmodifiable Collections: http://www.tutorialspoint.com/java/util/collections_unmodifiablelist.htm
Guava's immutable collections: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html
However, I notice both of them enforce the contract at runtime, by throwing exceptions (e.g UnsupportedOperationException).
Questions:
Are there existing libraries/language features that allow immutability checks to be performed at compile-time?
If not, why not? Is it because of a language limitation, the result of a design decision, or some other reason?
The original authors of the Collections APIs (unfortunately) did not make a distinction between immutable and mutable collections. An immutable API would have no mutating methods (but would likely rebuild collections internally as Persistent data structure).
See Scala as an example of a Collections API on the JVM that supports both immutable and mutable collections.
You could only do this by having no mutating methods on the class. But you're stuck if you want to implement an existing interface that has methods with mutating semantics (even static analysis won't help you in the general case).
This question already asked before but I don't find good understandable answer from there.
I would actually want to know that unlike c++ class objects can't be created statically in java why ? and what are the main disadvantages to create objects statically that java designers want to prevent to be occur ?
Thanks.
Good question. One is tempted to say that it is because the
authors of the language knew better than you what value types
you need, and provided them, and didn't want to let you define
new ones (e.g. like Complex). And there's certainly some of
that: it also explains the lack of operator overloading.
But I suspect that that wasn't the reason in the minds of the
Java authors. You need dynamic allocation and pointers (what
Java calls references) in some cases, such as when polymorphism
is involved, and the Java authors simply decided that they would
only support this idiom, rather than making the language more
complex by having it support several different idioms. It's
a pain, of course, when you actually need value semantics, but
with care, you can simulate them (java.lang.String would be
a good example) by making the class final and immutable, with
"operators" which return a new instance.
Of course, the added expressiveness of C++ does give more
possibility for errors: it's easy to take the address of a local
variable, for example, and end up with a dangling pointer. But
just because you can do something doesn't mean that you have to;
in C++, an incompetent programmer can make the program crash
immediately, where as in Java, he'll generally end up with
a wrong result (although uncaught exceptions aren't that rare
either).
Edit: It appears the poster may actually be asking why can't Objects be static in Java?, in which case, the answer is "they can" and I have added that to the answer at the bottom. If however the question is why can't Objects be allocated on the stack as they can in C++ then the first part of this answer attempts to deal with that:
I guess it boils down to the design goals of the Java language.
Because java has a garbage collector it doesn't really need to have stack allocated objects.
Trying to make things simpler, safer, familiar, while keeping them fast and consistent were design goals of the Java language designers.
Quoting from here http://www.oracle.com/technetwork/java/simple-142339.html (emphasis is mine):
Simplicity is one of Java's overriding design goals. Simplicity and
removal of many "features" of dubious worth from its C and C++
ancestors keep Java relatively small and reduce the programmer's
burden in producing reliable applications. To this end, Java design
team examined many aspects of the "modern" C and C++ languages to
determine features that could be eliminated in the context of modern
object-oriented programming.
One of those features that the designers decided was of "dubious worth" (or unnecessarily complicated the language or its Garbage Collection processes) were stack-allocated Objects.
These online chapters cover the design goals of the Java language in-depth.
Reviewing the comments I believe that I may have misinterpretted the original poster's question because the question seems to be confusing the two completely orthogonal concepts of allocating Objects on the stack with statically allocated Objects.
Stack allocation refers to value Objects that exist only within their current scope and occupy space on the stack.
Static allocation refers to instances that exist per Class - Objects that can exist for the lifetime of the application and are initialized within a static allocation block.
Java doesn't support the former concept (except with primitive data types) for the reasons explained above; but it certainly does support the latter. It is perfectly acceptable Java code to instantiate a static Object belonging to a class. A very simple example of a static Class Object would be this snippet of code:
public class Foo {
public static Integer integerValue = new Integer(32);
}
This would create a single public instance of an Integer Object that belongs to the class Foo. Because it is public in this example, one could access it and set it by calling:
Foo.integerValue = 57;
Note that only one (effectively global) copy exists of the integerValue regardless of how many Foo instances are instantiated.
A common use of statics is for class constants (declared with the the final modifier), but static variables in Java do not have to be constant: they are mutable by default if you omit the final modifier. Static variables need to be used with caution in multi-threaded applications, but that's another story.
For more information on static variables in java, you can read about them here:
http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
and here:
http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Hopefully the helps.
Generally speaking, the more I use immutable objects in Java the more I'm thinking they're a great idea. They've got lots of advantages from automatically being thread-safe to not needing to worry about cloning or copy constructors.
This has got me thinking, would an "immutable" keyword go amiss? Obviously there's the disadvantages with adding another reserved word to the language, and I doubt it will actually happen primarily for the above reason - but ignoring that I can't really see many disadvantages.
At present great care has to be taken to make sure objects are immutable, and even then a dodgy javadoc comment claiming a component object is immutable when it's in fact not can wreck the whole thing. There's also the argument that even basic objects like string aren't truly immutable because they're easily vunerable to reflection attacks.
If we had an immutable keyword the compiler could surely recursively check and give an iron clad guarantee that all instances of a class were immutable, something that can't presently be done. Especially with concurrency becoming more and more used, I personally think it'd be good to add a keyword to this effect. But are there any disadvantages or implementation details I'm missing that makes this a bad idea?
In general, immutable objects should be preferred over stateful objects, and it's currently fairly difficult to make an immutable object in Java. In fact, most OO languages have poor support for immutable objects, while most functional languages take them for granted, such as F#, Haskell, and Clojure.
Adding an immutable keyword to Java could make code...
Easier to write. No messing with final and private, no accidentally adding a method that makes the class mutable, and possibly no manually marking the class final (subclasses can add mutable state).
Easier to read. You don't need to say that the class is immutable in English, you can say it in the code itself. An immutable keyword is a good step toward self-documenting code.
Faster (theoretically). The more the compiler knows about your code, the more optimizations it can make. Without this keyword, every call to new ImmutableFoo(1, 2, 3) must create a new object, unless the compiler can prove that your class can't be mutated. If ImmutableFoo was marked with the immutable keyword, every such call could return the same object. I'm pretty sure new must always create a new object, which makes this point invalid, but effective communication with the compiler is still a good thing.
Scala's case classes are similar to an immutable keyword. An immutable keyword was also being considered in C# 5.
While making all fields final and also verifying any class references are also immutable is possible there are other situations where this becomes impossible.
What if your final class also includes some lazy loaded fields ?
One would need further support for marking such fields as immutable and lazy.
Taking a look at java.lang.String with its array of chars[] how could the compiler really know for sure that it is immutable ? Everybody knows string is but another similar class could very easily include a method which updates an array. Further support would need to verify that once the field was set, no other instruction could "write" to the array. Before long this becomes a very complex problem.
In the end any such keyword if it did work might help, but it still does not mean programs are any better. Good design by good coders means better results. Dumb coders can still write crap even if the platform limits some pitfalls.
I'm a big fan of immutability, so in my opinion, absolutely. The advantages of immutability in OO programming are innumerable, and it shouldn't be the domain of just functional programming languages.
IMHO, object-oriented frameworks (Java, .net, etc.) should include more array types: mutable array, immutable array, mutable array references, immutable array references, and read-only array references (a read-only reference could point to either a mutable or immutable array, but in neither case would allow writing). Without an immutable array type, it's hard to construct many efficient types in a way that can be proven to be immutable.
Some classes in the standard Java API are treated slightly different from other classes. I'm talking about those classes that couldn't be implemented without special support from the compiler and/or JVM.
The ones I come up with right away are:
Object (obviously) as it, among other things doesn't have a super class.
String as the language has special support for the + operator.
Thread since it has this magical start() method despite the fact that there is no bytecode instruction that "forks" the execution.
I suppose all classes like these are in one way or another mentioned in the JLS. Correct me if I'm wrong.
Anyway, what other such classes exist? Is there any complete list of "glorified classes" in the Java language?
There are a lot of different answers, so I thought it would be useful to collect them all (and add some):
Classes
AutoBoxing classes - the compiler only allows for specific classes
Class - has its own literals (int.class for instance). I would also add its generic typing without creating new instances.
String - with it's overloaded +-operator and the support of literals
Enum - the only class that can be used in a switch statement (soon a privilege to be given to String as well). It does other things as well (automatic static method creation, serialization handling, etc.), but those could theoretically be accomplished with code - it is just a lot of boilerplate, and some of the constraints could not be enforced in subclasses (e.g. the special subclassing rules) but what you could never accomplish without the priviledged status of an enum is include it in a switch statement.
Object - the root of all objects (and I would add its clone and finalize methods are not something you could implement)
References: WeakReference, SoftReference, PhantomReference
Thread - the language doesn't give you a specific instruction to start a thread, rather it magically applies it to the start() method.
Throwable - the root of all classes that can work with throw, throws and catch, as well as the compiler understanding of Exception vs. RuntimeException and Error.
NullPointerException and other exceptions such as ArrayIndexOutOfBounds which can be thrown by other bytecode instructions than athrow.
Interfaces
Iterable - the only interface that can be used in an enhanced for loop
Honorable mentions goes to:
java.lang.reflect.Array - creating a new array as defined by a Class object would not be possible.
Annotations They are a special language feature that behaves like an interface at runtime. You certainly couldn't define another Annotation interface, just like you can't define a replacement for Object. However, you could implement all of their functionality and just have another way to retrieve them (and a whole bunch of boilerplate) rather than reflection. In fact, there were many XML based and javadoc tag based implementations before annotations were introduced.
ClassLoader - it certainly has a privileged relationship with the JVM as there is no language way to load a class, although there is a bytecode way, so it is like Array in that way. It also has the special privilege of being called back by the JVM, although that is an implementation detail.
Serializable - you could implement the functionality via reflection, but it has its own privileged keyword and you would spend a lot of time getting intimate with the SecurityManager in some scenarios.
Note: I left out of the list things that provide JNI (such as IO) because you could always implement your own JNI call if you were so inclined. However, native calls that interact with the JVM in privileged ways are different.
Arrays are debatable - they inherit Object, have an understood hierarchy (Object[] is a supertype of String[]), but they are a language feature, not a defined class on its own.
Class, of course. It has its own literals (a distinction it shares with String, BTW) and is the starting point of all that reflection magic.
sun.misc.unsafe is the mother of all dirty, spirit-of-the-language-breaking hacks.
Enum. You're not allowed to subclass it, but the compiler can.
Many things under java.util.concurrent can be implemented without JVM support, but they would be a lot less efficient.
All of the Number classes have a little bit of magic in the form of Autoboxing.
Since the important classes were mentioned, I'll mention some interfaces:
The Iterable interface (since 1.5) - it allows an object to participate in a foreach loop:
Iterable<Foo> iterable = ...;
for (Foo foo : iterable) {
}
The Serializable interface has a very special meaning, different from a standard interface. You can define methods that will be taken into account even though they are not defined in the interface (like readResolve()). The transient keyword is the language element that affects the behaviour of Serializable implementors.
Throwable, RuntimeException, Error
AssertionError
References WeakReference, SoftReference, PhantomReference
Enum
Annotation
Java array as in int[].class
java.lang.ClassLoader, though the actual dirty work is done by some unmentioned subclass (see 12.2.1 The Loading Process).
Not sure about this. But I cannot think of a way to manually implement IO objects.
There is some magic in the System class.
System.arraycopy is a hook into native code
public static native void arraycopy(Object array1, int start1,
Object array2, int start2, int length);
but...
/**
* Private version of the arraycopy method used by the jit
* for reference arraycopies
*/
private static void arraycopy(Object[] A1, int offset1,
Object[] A2, int offset2, int length) {
...
}
Well since the special handling of assert has been mentioned. Here are some more Exception types which have special treatment by the jvm:
NullPointerException
ArithmeticException.
StackOverflowException
All kinds of OutOfMemoryErrors
...
The exceptions are not special, but the jvm uses them in special cases, so you can't implement them yourself without writing your own jvm. I'm sure that there are more special exceptions around.
Most of those classes isn't really implemented with 'special' help from the compiler or JVM. Object does register some natives which poke around the internal JVM structures, but you can do that for your own classes as well. (I admit this is subject to semantics, "calls a native defined in the JVM" can be considered as special JVM support.)
What /is/ special is the behaviour of the 'new', and 'throw' instructions in how they initialise these internal structures.
Annotations and numbers are pretty much all-out freaky though.