Here is a list of issues I came across when working with Java. I have strong C/C++ and Windows OS background, so some of the issues maybe biased.
The language guarantees that reading or writing a single variable is atomic unless the variable is of type long or double ... While the atomicity guarantee ensures that a thread will not see a random value when reading atomic data, it does not guarantee that a value written by one thread will be visible to another (Bloch, Effective Java, Item 48).
The synchronized
and volatile
has quite different
effects on code:
synchronize
guaranties, that onle one thread can enter a block
of code. But it doesn't guarantee, that variables modifications done within
synchronized section will be visible to other threads. Only the threads that
enters the synchronized block is guarantieed to see the changes. This is the reason
why double checked locking is broken - it is not synchronized on reader's side.
Reading thread may see, that singleton is not null, but singleton data
may not be fully initialized (visible). Enter to synchronize
block is read barrier and leave of
synchronize
block is write barrier. In the case on readers/writers volatile
read is read barrier and volatile
write is write barrier, for instance
write to volatile singleton static field guaranties that writes to the singleton object will be finished
before the write to volatilie static field. However it doesn't prevent creation
singleton of two objects, this is provided by synchronize
public class Singleton { private static class SingletonHolder { private final static Singleton singleton = new Singleton(); } public static Singleton getSingleton() { return SingletonHolder.singleton; } private Singleton() { ... } ... }
java.util.concurrent.atomic
has a small toolkit of classes
that support lock-free thread-safe programming on single variables.
Java thread scheduling is not fair. It is not difficult to create so many working threads
If you do not specify the identification number explicitly by declaring a private static final long field named serialVersionUID, the system automatically generates it by applying a complex deterministic procedure to the class. The automatically generated value is affected by the class's name, the names of the interfaces it implements, and all of its public and protected members. If you change any of these things in any way, for example, by adding a trivial convenience method, the automatically generated serial version UID changes. If you fail to declare an explicit serial version UID, compatibility will be broken. (Bloch, Effective Java, Item 54)
If the jar version information is not part of the jar name or it is not
written in META-INF/MANIFEST.MF, it is not easy to get it.
You can use Google, MD5 checksum and Maven repository. Make MD5 checksum
of the jar (you can use md5sum or its
windows port) and
then search it in Google prepending site:www.ibiblio.org
to the query.
I was not clear to me how JBoss Application Server can run the web server and JavaEE container in the same JVM and how the memory used by the processes is separated. Here are link that explains the magic:
Dynamic Proxy Classes and Explore Dynamic Proxy API. Dynamic proxy API can be used for various purposes, for instance access control proxy, facade proxy, remote proxy, methods interposing.
Using java.lang.reflect.Proxy to Interpose on Java Class Methods. There is a United States Patent 7093242 on Dynamic class interposition
There is no support for setting process priority for processes
started through Runtime.Exec()
or ProcessBuilder
.
Each OS manages priorities in different way, some OS don't have priorities at all.
Jakarta commons-exec
seems to use the methods mentioned above.
The Java 2 Platform, Standard Edition (J2SE) 5.0 release provides comprehensive monitoring and management support. You can observe information about an application running on the Java platform. Look at jconsole.
Unfortunately Java doesn't have true constant instances. The final keyword can be applied to primitive types and to a reference type. But final on reference type means, that the reference will not change, the referenced object may change!
If you want to have constant object, or something similar to constant object, you can:
There are several variants to this pattern, see java final vs. c++ const
In C/C++ the const is also used as a documentation tool. When a function or method doesn't modify object passed as parameter, that parameter is marked as const. Because java doesn't use true constants, this is of no use. You can mark parameters as final, but final is not considered part of the method signature.
There are three reasons why to use final on local variables:
For more read The Final Word On the final Keyword.
Because there is no API to unmap a memory mapped file, you cannot reliably delete the file once you mapped it. According to Sun, this bug will not be fixed. See Sun's Bug Database:
You may use the following trick to force unmap with forced garbage collection:
final MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, size); .... final WeakReferencebufferWeakRef = new WeakReference (bb); bb = null; final long startTime = System.currentTimeMillis(); while(null != bufferWeakRef.get()) { if(System.currentTimeMillis() - startTime > 10) // give up return; System.gc(); Thread.yield(); }
Boolean.getBoolean(String) seems like perfect function name when you want to convert from String to boolean primitive. Nope. getBoolean(String) reads system property. Most of the time you want to call Boolean.parseBoolean(String). This shortcut function is source of troubles, it should be deprecated.
Of course the same applies for Integer.getInteger(String), Long.getLong(String).