Couple of questions

13 views
Skip to first unread message

Richard Achmatowicz

unread,
Feb 13, 2008, 5:08:29 PM2/13/08
to JCarder
Hello

I have two questions as I try and improve my understanding of JCarder:

1. Can you give me an example of what you refer to as a single thread
cycle. I'm not sure i've got the concept.

2. I'm running JCarder on some small concurrent programs which employ
synchronized methods (which will take locks on object instances), but
when I run the analyser, there are no nodes in the lock acqusition
graph. Does the lock acquisition graph represent all locks taken using
synchronized methods and synchronized blocks?

An example of the kind of program i'm running follows:

import java.util.List ;
import java.util.LinkedList ;
import java.util.Collections ;

public class WaitNotifyTest {

Queue q = null ;
Thread t1 = null ;
Thread t2 = null ;
boolean running = false ;

public WaitNotifyTest() {

// initialise the shared queue
q = new Queue() ;

// initialise the workers
t1 = new QueueSender() ;
t2 = new QueueReceiver() ;
}

public void start() {
running = true ;
t1.start() ;
t2.start() ;
}

public void stop() {
running = false ;
}

public static void main(String[] args) {

WaitNotifyTest t = new WaitNotifyTest() ;
t.start() ;

try {
Thread.sleep(2 * 1000) ;
}
catch(InterruptedException e) {
}
t.stop() ;
}

class QueueSender extends Thread {

int count = 0 ;

public void run() {

// just add items to the queue
while (running) {

Integer i = new Integer(count) ;
q.push(i) ;
System.out.println("object sent = " + i) ;
count++ ;

if (count % 1000 == 0)
Thread.yield() ;
}

System.out.println("Sender terminating") ;

// just in case the receiver is blocked
Integer i = new Integer(count) ;
q.push(i) ;

}
}

class QueueReceiver extends Thread {

public void run() {

// just add items to the queue
while (running) {

Integer i = (Integer) q.pop() ;
System.out.println("object received = " + i) ;

// try {
// Thread.sleep(100) ;
// }
// catch(InterruptedException e) {
// }
}
System.out.println("Receiver terminating") ;
}
}

/**
* An inner class to represent a worker thread
*/
class Queue {

LinkedList q = new LinkedList() ;

synchronized public void push(Object o) {
q.add(o) ;

// we know there is at least one object

// notify anyone waiting on the object Queue
this.notify() ;
}

synchronized public Object pop() {

while (q.size() == 0) {
// add ourself to the list of threads waiting on Queue

// when Queue.notify() is called, we will be woken up
// and continue
try {
this.wait() ;
}
catch(InterruptedException e) {
}
}

// we know there is at least one object
// so return it
return q.remove(0) ;
}
}
}

Richard Achmatowicz

unread,
Feb 14, 2008, 12:00:23 PM2/14/08
to JCarder
I found the example of single thread cycle in the repo. Think i've got
it now.

Still wondering about why JCarder doesn't record entries for locks
taken in my example.

Also wondering why your tool doesn't handle classes from
java.util.concurrent, which we use a great deal. What's the
explanation, if it isn't too technical!

On Feb 13, 5:08 pm, Richard Achmatowicz

Richard Achmatowicz

unread,
Feb 14, 2008, 2:07:01 PM2/14/08
to JCarder
I've reorganized the example above so that it doesn't use inner
classes, and still get the same result from jcarder:

[nrla@localhost jcarderstuff]$ java -jar /tmp/jcarder-1.0.1/
jcarder.jar -outputmode all

Opening for reading: /tmp/jcarderstuff/jcarder_contexts.db
Opening for reading: /tmp/jcarderstuff/jcarder_events.db

Loaded from database files:
Nodes: 0
Edges: 0 (excluding 0 duplicated)

Cycle analysis result:
Cycles: 0
Edges in cycles: 0
Nodes in cycles: 0
Max cycle depth: 0
Max graph depth: 0

No cycles found!

Am I doing something wrong?

On Feb 14, 12:00 pm, Richard Achmatowicz

Ulrik Svensson

unread,
Feb 14, 2008, 3:50:37 PM2/14/08
to jca...@googlegroups.com
Hello Richard,

you are not doing anything wrong and JCarder is able to handle inner
classes as well as normal classes.

JCarder stores all graph edges in the database files. An edge
represents the acquiring of a lock while already holding one (or more)
other locks. The edge is directed, from the most recently taken lock,
to the new lock being acquired.

If a thread acquires a lock without already holding any other locks,
no edge will be created by JCarder. It is perfectly ok, since
acquiring only one lock at a time can never lead to a deadlock.

Nodes (locks) without any edges are not stored in the database files
for performance reasons.

In your example there is only a single lock (the Queue instance) that
is synchronized on, therefore no edges are created or stored.

I hope this is answering your question?

/Ulrik

Richard Achmatowicz

unread,
Feb 15, 2008, 10:45:47 AM2/15/08
to JCarder
Hi Ulrik

The clouds are beginning to clear...Thank you for a concise and clear
explanation! I was under the incorrect impression that -outputmode all
showed all locking activity, even of the type you have now explained
is excluded.

But what about java.util.concurrent? Why does JCarder not take these
classes into account, and are there any plans in future to incorporate
them?

Or let me put the question in a different way: which forms of locking
activity does JCarder take into account? Is it solely locks acquired
when using synchronized methods and synchronized blocks? Or are there
other examples of locking which can be used in Java and where JCarder
will incorporate those locking styles into its acqusition graph?

On Feb 14, 3:50 pm, "Ulrik Svensson" <ulri...@gmail.com> wrote:
> Hello Richard,
>
> you are not doing anything wrong and JCarder is able to handle inner
> classes as well as normal classes.
>
> JCarder stores all graph edges in the database files. An edge
> represents the acquiring of a lock while already holding one (or more)
> other locks. The edge is directed, from the most recently taken lock,
> to the new lock being acquired.
>
> If a thread acquires a lock without already holding any other locks,
> no edge will be created by JCarder. It is perfectly ok, since
> acquiring only one lock at a time can never lead to a deadlock.
>
> Nodes (locks) without any edges are not stored in the database files
> for performance reasons.
>
> In your example there is only a single lock (the Queue instance) that
> is synchronized on, therefore no edges are created or stored.
>
> I hope this is answering your question?
>
> /Ulrik
>
> On Thu, Feb 14, 2008 at 8:07 PM, Richard Achmatowicz
>

Ulrik Svensson

unread,
Feb 17, 2008, 2:19:56 PM2/17/08
to jca...@googlegroups.com
Hi Richard,

yes, maybe we should clarify exactly what information is included by
the "-outputmode all" parameter in the documentation.

Right now JCarder analyzes synchronized methods and synchronized
blocks, nothing else.

We have ideas about also analyzing the locks from
java.util.concurrent.locks and the synchronization performed in other
parts of the standard library.

I see two different approaches for that: Either instrument the
standard library itself or instrument the invocations from the user
code to the standard library. Both alternatives have different issues,
pros and cons.

We have also ideas about looking for data races, in addition to deadlocks.

I don't know when we will have time to work on this. Help is always welcome! :-)

/Ulrik

On Feb 15, 2008 4:45 PM, Richard Achmatowicz

Reply all
Reply to author
Forward
0 new messages