[JBoss Microcontainer Development] - Re: Testing Deployers with new Reflect + ClassPool
by alesj
"flavia.rainone(a)jboss.com" wrote :
| This is what I'll do. I'll leave the parent as null in the case above, which will make the exclusion mechanism work. And I'll try to filter out classes belonging to java.* and com.sun.* packages. Every class name that matches those will have an universal CtClass created for it (following the same that is done for primitives in the ClassPool), associated with a null ClassPool. For obvious reasons, I'm not very fond of this approach, but I think it is worth a shot, since it is this or implementing exclusion for classpools. Plus, I think it is the closest we can get to the ClassLoader's behaviour.
OK, I see what you mean, and you have a point there. :-)
I wouldn't go with this null, but just with a simple CP exclude -- only for tests purposes.
e.g.
Map the AppCL with DefaultCP, but somehow exclude all but java.* and our test packages.
Actually make this exclusion configurable, as we have it in CL/Deployers.
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4269786#4269786
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4269786
14 years, 5 months
[JBoss Messaging Development] - Here is How I solve A Hang Problem
by gaohoward
To make sure all ongoing calls on an object are finished before closing the object, an interceptor is used
| public class ClosedInterceptor
| {
|
| //synchronization is omitted here as irrelevant to the issue.
| public Object invoke(invocation)
| {
| if (method_is_close)
| {
| while (inUseCount > 0)
| {
| wait();
| }
| //now safely in close state.
| }
| else
| {
| ++inUseCount;
| invoke_method();
| --inUseCount;
| notifyAll();
| }
| }
| }
|
You can see if the object's close() is being called by some thread, it will wait there until the inUserCount is zero.
But a calling thread may hang in waiting if the following call sequence happens:
1. The calling thread call a normal method on the object.
2. The interceptor intercepts the call, increase inUseCount by one and go on to call the real method.
3. During the mothod call, some failure happened and as part of the failure handling, relavent resources will be closed, including this object. So the object's close() is called.
4. The interceptor intercepts the close() call, as the inUseCount has been increased by one, it will wait there.
5. The result is that the thread is waiting for itself to return, which will never happen.
To slove the problem, I think the key is to avoid the calling thread waiting on itself. For this purpose, I write a ThreadValveCounter util class. Using this class, the above code can be re-written as:
| public class ClosedInterceptor
| {
| ThreadValveCounter counter = new ThreadValveCounter();
|
| //synchronization is omitted here as irrelevant to the issue.
| public Object invoke(invocation)
| {
| if (method_is_close)
| {
| if (closed)
| {
| return;
| }
|
| counter.waitForCompletion();
| //now safely in close state.
| }
| else
| {
| counter.pushThread();
| object.invokeMethod(method);
| counter.popThread();
| }
| }
| }
|
and Below is the code of ThreadValveCounter
| import java.util.Iterator;
| import java.util.concurrent.ConcurrentHashMap;
|
| /**
| * A ThreadValveCounter
| *
| * This is a utility class to avoid a calling thread waiting on itself. In cases where an object is accessed concurrently,
| * closing that object requires first waiting for all the current ongoing calls to be finished, which means all current calling
| * threads (except the one who is calling close()) returning from their respective method calls on that object. Sometimes
| * the calling thread who is calling close() can come from one of those who are calling normal methods. In that situation
| * this calling thread will wait forever as it is waiting itself to return.
| *
| * This class keeps a per-thread counter to avoid the above deadlock. Before waiting, the thread can use this class
| * to exempt itself from the counter, thus eliminating the possibility of hang on itself.
| *
| * @author <a href="mailto:hgao@redhat.com">Howard Gao</a>
| *
| * Created Dec 9, 2009 4:37:14 PM
| *
| *
| */
| public class ThreadValveCounter
| {
|
| private ConcurrentHashMap<Long, IntHolder> threadCounter = new ConcurrentHashMap<Long, IntHolder>();
|
| public void pushThread()
| {
| Long tid = Thread.currentThread().getId();
| IntHolder counter = threadCounter.get(tid);
| if (counter == null)
| {
| counter = new IntHolder();
| threadCounter.put(tid, counter);
| }
| counter.add();
| }
|
| public int popThread()
| {
| IntHolder counter = threadCounter.get(Thread.currentThread().getId());
| if (counter != null)
| {
| if (counter.release() == 0)
| {
| synchronized(threadCounter)
| {
| threadCounter.notifyAll();
| }
| }
| }
| return 0;
| }
|
| public void waitForCompletion()
| {
| exemptCurrentThread();
| synchronized (threadCounter)
| {
| while (getCallCount() > 0)
| {
| try
| {
| threadCounter.wait();
| }
| catch (InterruptedException e)
| {
| //ignore
| }
| }
| }
| }
|
| private void exemptCurrentThread()
| {
| IntHolder counter = threadCounter.get(Thread.currentThread().getId());
| if (counter != null)
| {
| counter.clear();
| }
| synchronized(threadCounter)
| {
| threadCounter.notifyAll();
| }
| }
|
| private int getCallCount()
| {
| synchronized(threadCounter)
| {
| Iterator<IntHolder> iter = threadCounter.values().iterator();
| int total = 0;
| while (iter.hasNext())
| {
| total += iter.next().get();
| }
| return total;
| }
| }
|
| private static class IntHolder
| {
| private int counter = 0;
|
| public void add()
| {
| counter++;
| }
|
| public int get()
| {
| return counter;
| }
|
| public int release()
| {
| counter--;
| return counter;
| }
|
| public void clear()
| {
| counter = 0;
| }
| }
|
| }
|
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4269778#4269778
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4269778
14 years, 5 months
[JBoss Microcontainer Development] - Re: Testing Deployers with new Reflect + ClassPool
by flavia.rainone@jboss.com
"Ales" wrote : If the CP works properly on top of CL, it should not need such exclusion.
I see your point. If the CP mimics the ClassLoader perfectly, it shouldn't have this problem. The problem here is that the CP doesn't mimic it perfectly.
For every classloader that is not a RealClassLoader, the JBossClDelegatingClassPoolFactory replaces a null parent by a default classPool:
if (parent == null)
| {
| parent = ClassPool.getDefault();
| }
| return new NonDelegatingClassPool(cl, parent, repository, true);
For example, if we have a URLClassLoader as the parent of a domain, the JBossClDelegatingCPFactory will create a NonDelegatingclassPool using the piece of code above to represent the parent of the domain. And, since the URLClassLoader, in cases like this, has a null parent, the factory will set the default ClassPool as the parent of the NonDelegatingClassPool (the Default ClassPool is a classpool that contains the system classpath).
Because of such a non-null parent, the exclusion is not working for class pools. :-(
On the other hand, if we kept the parent classpool as null, and if this non delegating classpool is required to load, say, java.lang.String, it will return a CtClass created by the NonDelegatingClassPool itself. This results in duplicates. Another NonDelegatingClassPool willl create its own CtClass representing String.class and so on. I'm not sure what are the consequences of this.
Interestingly, this problem doesn't occur with primitives. Javassist has an array of CtPrimitiveTypes, a subclass of CtClass, representing each one of the primitive types. The same collection is used for all classpools and if you try to get the classpool that loaded the primitive type, you get a null classpool. That's what I would like to see with a CtClass representing a String, for example. But creating a CtClass array with all classes of the bootstrap classpath is cumbersome, to say the least.
This is what I'll do. I'll leave the parent as null in the case above, which will make the exclusion mechanism work. And I'll try to filter out classes belonging to java.* and com.sun.* packages. Every class name that matches those will have an universal CtClass created for it (following the same that is done for primitives in the ClassPool), associated with a null ClassPool. For obvious reasons, I'm not very fond of this approach, but I think it is worth a shot, since it is this or implementing exclusion for classpools. Plus, I think it is the closest we can get to the ClassLoader's behaviour.
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4269699#4269699
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4269699
14 years, 5 months
[JBoss Microcontainer Development] - Re: Testing Deployers with new Reflect + ClassPool
by flavia.rainone@jboss.com
"alesj" wrote : "flavia.rainone(a)jboss.com" wrote :
| | - a few of the ClassPool tests are broken. I'll have to mimic the excludes mechanism in the ClassPools in order to have these tests working.
| |
| If the CP works properly on top of CL, it should not need such exclusion.
|
I also thought so, but I was wrong.
The ClassPools have their own parent and domain delegation structure, that mimics the ClassLoader's parent and domain structure. So, when we ask for a ClassPool to load a class, it will use this delegation structure to find and load the class. At the point that the delegation reaches the ClassPool corresponding to the AppClassLoader (the parent of default domain), the classpool is able of loading classes in excluded package. IMO, the only way of avoiding this is aborting the load of the class if it is in the excluded package. That's the same as saying that I have to mimic the exclusion mechanism with the classpools.
View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4269690#4269690
Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4269690
14 years, 5 months