I'm not entirely sure how I got to this situation but somehow I'm getting a null ClassLoader from Thread.getContextClassLoader. After reading a little (not much info in the docs nor on google) I got the impression that it's valid for the current thread to have a null class loader, and calls to getContextClassLoader should be checked for a null reference.
This is quite surprising since I've seen a couple of open source projects unchecked calls to getContextClassLoader (which got me to checking this in the first place). Specifically, this line in codemodel: JCodeModel.java line 358
(I just verified that log4j doesn't check as well)
So should calls to getContextClassLoader check for a null reference or is something messed up with my threads?
It's quite valid for Thread.getContextClassLoader to return null. Not all software is of particularly good quality.
Whilst null ClassLoader typically refers to the boot class loader that loads the system classes (I think that's right - the terminology is messed up for historical reasons), for thread context class loaders it is usually interpreted as unset, and the system class loader is used instead.
IIRC, the thread context class loader is set to the system class loader for the main thread if using the java command. For applets the applet thread and EDT have it set to the applet class loader.
I would suggest not using thread context class loaders (or most other thread locals), unless the context requires it.
As Tom says, it is perfectly valid for Thread.getContextClassLoader() to return null. I vaguely recall that the default behaviour has changed over time (or it could have been different in various JVM vendor implementations - I can't remember).
Assuming a non-null context ClassLoader may be valid if you've set one further up the stack and don't have foreign code in between, or if the class/library contract requires one.
As a side note, Class.getClassLoader() can return null too.
Related
I see a lot of classes that extend javax.annotation.processing.AbstractProcessor,
and override the init member, making it synchronous.
For example: https://github.com/weibocom/motan/blob/master/motan-core/src/main/java/com/weibo/api/motan/transport/async/MotanAsyncProcessor.java#L61
I picture this function being called exclusively by the javac compiler, and if "synchronous" were necessary, I would expect to see something about it in Oracle's documentation of AbstractProcessor (but I do not).
https://docs.oracle.com/javase/7/docs/api/javax/annotation/processing/AbstractProcessor.html for reference.
Also, while I see init synchronous, I don't see process synchronous.
Oracle's documentation about the init member does say, "An IllegalStateException will be thrown if this method is called more than once on the same object." But I don't see how that would figure in. I guess I can imagine a scenario where we want to be careful that exactly one thread calls init successfully (thus synchronize), and then only that successful thread gets to call process. But that's quite a flight of imagination without documentation to back it up.
So, is it necessary to specify "synchronous" for our init members of classes inherited from AbstractProcessor? Why or why not? And if it is necessary, why isn't it necessary to make process synchronous too?
Anyone have any insight?
Thanks! - Jim
The main question is about static fields and singleton instances (for configs, etc.) - are instances of one process running in different threads, as usual servlet requests?
If look deeper - do different #ProcessApplication run in one JVM and will see the same singletons? I don't think so. I know exactly that their classes don't see each other and can have equal names (because of different classLoaders?)
Haven't found any meaningful info on these important themes about Camunda, will appreciate your answers.
I had this same question for one of our scenario while back, and read their Javadoc as mentioned here for a servlet container. Extracting Javadoc,
Invocation Semantics
When the {#link #execute(java.util.concurrent.Callable)} method is
invoked, the servlet process application modifies the context
classloader of the current Thread to the classloader that loaded the
application-provided subclass of this class. This allows,
the process engine to resolve {#link JavaDelegate} implementations using the classloader of the process application
This pretty much explain everything you want to know, since the behavior is very similar to how a web container operates. If you want to know how other container implementations behaves, you can check the respective Javadocs of classes in this package.
To answer your question:
Yes. Thread-safety is required for the shared-resources accessed by JavaDelegate in the same process application. According to the documentation (see below) they create a new instance of delegate each time a task is going to be executed.
Note!
Each time a delegation class referencing activity is executed, a
separate instance of this class will be created. This means that each
time an activity is executed there will be used another instance of
the class to call execute(DelegateExecution).
Therefore, at any time there can be many delegate instances actively running due to the multiple invocation of Process Definitions. So, if they are accessing a shared resource, then they need to be synchronized (thread-safe), because, that shared resources (static or singleton) is local to the process application and loaded by respective application classloader according to above Invocation Semantics Javadoc.
Hope this helps.
How unique is the thread context's classloader. Is it reset everytime a thread is started?
Can we always be sure that 2 parallel threads will never have the same context classloader?
I see some frameworks like Axis relying on this to get and set run-time setting variables.
How unique is the thread context's classloader.
Not even remotely.
Is it reset everytime a thread is started?
When a thread is created, it doesn’t have context loader that can be reset. It will inherit the parent thread’s context loader. Starting the thread doesn’t change its context loader.
Can we always be sure that 2 parallel threads will never have the same context classloader?
That would be actually very unlikely. As said, threads inherit the parent’s loader by default, so unless someone calls setContextClassLoader explicitly with a different loader, the default application class loader, as returned by ClassLoader.getSystemClassLoader() will be the used by all threads. Even in environments with different class loaders, it’s unlikely to have as much class loaders as threads.
I see some frameworks like Axis relying on this to get and set run-time setting variables.
It’s the main use of the feature, frameworks using the current thread’s context class loader by convention, but of course, for loading classes and resources, not to assume uniqueness of these loaders. The JVM never uses this context class loader on its own, as symbolic references found in a class are resolved through the defining class loader of that class. The same applies for Class.forName(String) (without a class loader argument). It requires code actively invoking getContextClassLoader() and using the returned loader for class loading, to make this feature relevant.
Don’t confuse class loaders with ThreadLocal variables.
Under IBM JVM we have faced an issue when multiple threads are trying to call Class.getAnnotation at the same time on different objects (but with the same annotation). Threads are starting to deadlock waiting on a monitor inside a Hashtable, which is used as a cache for annotations in IBM JVM. The weirdest thing is that the thread that is holding this monitor is put into 'waiting on condition' state right inside Hashtable.get, making all other threads to wait indefinitely.
The support from IBM stated, that implementation of Class.getAnnotation is not thread safe.
Comparing to other JVM implementations (for example, OpenJDK) we see that they implement Class methods in thread safe manner. IBM JVM is a closed source JVM, they do publish some source code together with their JVM, but it's not enough to make a clear judgment whenever their implementation of Class is thread safe or not.
The Class documentation doesn't clearly state whenever its methods are thread safe or not. So is it a safe assumption to treat Class methods (getAnnotation in particular) as a thread safe or we must use sync blocks in multi threaded environment?
How do popular frameworks (ex. Hibernate) are mitigating this problem? We haven't found any usage of synchronization in Hibernate code that was using getAnnotation method.
Your problem might be related to bug fixed in version 8 of Oracle Java.
One thread calls isAnnotationPresent on an annotated class where the
annotation is not yet initialised for its defining classloader. This
will result in a call on AnnotationType.getInstance, locking the class
object for sun.reflect.annotation.AnnotationType. getInstance will
result in a Class.initAnnotationsIfNecessary for that annotation,
trying to acquire a lock on the class object of that annotation.
In the meanwhile, another thread has requested Class.getAnnotations
for that annotation(!). Since getAnnotations locks the class object it
was requested on, the first thread can't lock it when it runs into
Class.initAnnotationsIfNecessary for that annotation. But the thread
holding the lock will try to acquire the lock for the class object of
sun.reflect.annotation.AnnotationType in AnnotationType.getInstance
which is hold by the first thread, thus resulting in the deadlock.
JDK-7122142 : (ann) Race condition between isAnnotationPresent and getAnnotations
Well, there is no specified behavior, so normally the correct way to deal with it would be to say “if no behavior is specified, assume no safety guarantees”.
But…
The problem here is that if these methods are not thread-safe, the specification lacks a documentation of how to achieve thread-safety correctly here. Recall that instances of java.lang.Class are visible across all threads of the entire application or even within multiple applications if your JVM hosts multiple apps/applets/servlets/beans/etc.
So unlike classes you instantiate for your own use where you can control access to these instances, you can’t preclude other threads from accessing the same methods of a particular java.lang.Class instance. So even if we engage with the very awkward concept of relying on some kind of convention for accessing such a global resource (e.g. like saying “the caller has to do synchronized(x.class)”), the problem here is, even bigger, that no such convention exists (well, or isn’t documented which comes down to the same).
So in this special case, where no caller’s responsibility is documented and can’t be established without such a documentation, IBM is in charge of telling how they think, programmers should use these methods correctly when they are implemented in a non-thread-safe manner.
There is an alternative interpretation I want to add: all information, java.lang.Class offers, is of a static constant nature. This class reflects what has been invariably compiled into the class. And it has no methods to alter any state. So maybe there’s no additional thread-safety documentation as all information is to be considered immutable and hence naturally thread-safe.
Rather, the fact that under the hood some information is loaded on demand is the undocumented implementation detail that the programmer does not need to be aware of. So if JRE developers decide to implement lazy creation for efficiency they must maintain the like-immutable behavior, read thread safety.
I'm part of a team that develops a pretty big Swing Java Applet. Most of our code are legacy and there are tons of singleton references. We've bunched all of them to a single "Application Context" singleton. What we now need is to create some way to separate the shared context (shared across all applets currently showing) and non-shared context (specific to each applet currently showing).
However, we don't have an ID at each of the locations that call to the singleton, nor do we want to propagate the ID to all locations. What's the easiest way to identify in which applet context we're running? (I've tried messing with classloaders, thread groups, thread ids... so far I could find nothing that will enable me to ID the origin of the call).
Singletons are evil, what do you expect? ;)
Perhaps the most comprehensive approach would be to load the bulk of the applet in a different class loader (use java.net.URLClassLoader.newInstance). Then use a WeakHashMap to associate class loader with an applet. If you could split most of the code into a common class loader (as a parent of each per-applet class loader) and into the normal applet codebase, that would be faster but more work.
Other hacks:
If you have access to any component, you can use Component.getParent repeatedly or SwingUtilities.getRoot.
If you are in a per-applet instance thread, then you can set up a ThreadLocal.
From the EDT, you can read the current event from the queue (java.awt.EventQueue.getCurrentEvent()), and possibly find a component from that. Alternatively push an EventQueue with a overridden dispatchEvent method.
If I understand you correctly, the idea is to get a different "singleton" object for each caller object or "context".
One thing you can do is to create a thread-local global variable where you write the ID of the current context. (This can be done with AOP.) Then in the singleton getter, the context ID is fetched from the thread-local to use as a key to the correct "singleton" instance for the calling context.
Regarding AOP there should be no problem using it in applets since, depending on your point-cuts, the advices are woven at compile time and a JAR is added to the runtime dependencies. Hence, no special evidence of AOP should remain at run time.
#Hugo regarding threadlocal:
I thought about that solution. However, from experiments I found two problems with that approach:
Shared thread (server connections, etc) are problematic. This can be solved though by paying special attention to these thread (they're all under my control and are pretty much isolated from the legacy code).
The EDT thread is shared across all applets. I failed to find a way to force the creation of a new EDT thread for each applet. This means that the threadlocal for the EDT would be shared across the applets. This one I have no idea how to solve. Suggestions?