SlideShare a Scribd company logo
How to find deadlock
not getting into it
Nikita Koval, Devexperts LLC
nkoval@devexperts.com
twitter.com/nkoval_
Other tracks are more interesting!
https://github.com/Devexperts/dlcheck
Slide 2/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Real-life
example
Slide 3/101. Copyright © 2017. Devexperts LLC. All rights reserved.
interface Con { // Connection
void onRegister(ConnectionManager cm);
void close();
}
class ConnectionManager {
Set<Con> cons = new HashSet<>();
synchronized void register(Con c) {
cons.add(c);
con.onRegister(this);
}
synchronized void unregister(Con c) {
cons.remove(c);
}
...
Slide 4/101. Copyright © 2017. Devexperts LLC. All rights reserved.
interface Con { // Connection
void onRegister(ConnectionManager cm);
void close();
}
class ConnectionManager {
Set<Con> cons = new HashSet<>();
synchronized void register(Con c) {
cons.add(c);
con.onRegister(this);
}
synchronized void unregister(Con c) {
cons.remove(c);
}
...
// ... ConnectionManager
synchronized int getConCount() {
return cons.size();
}
synchronized void closeAll() {
for (Con c: cons)
c.close();
}
}
Slide 5/101. Copyright © 2017. Devexperts LLC. All rights reserved.
class ConnectionImpl implements Con {
ConnectionManager cm;
@Override
public synchronized void onRegister(ConnectionManager cm) {
this.cm = cm;
}
@Override
public synchronized void close() {
if (cm != null) {
cm.unregister(this);
cm = null;
}
}
}
Slide 6/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Run functional test…
Works well!
Run stress test…
Slide 7/101. Copyright © 2017. Devexperts LLC. All rights reserved.
public void test() throws Exception {
ConnectionManager cm = new ConnectionManager();
new Thread(() -> {
while (true) {
Connection con = new ConnectionImpl();
cm.register(con);
con.close(); // lock con -> lock cm
}
}).start();
for (int i = 1; i < 100_000; i++) {
System.out.println("Iteration #" + i);
cm.closeAll(); // lock cm -> lock con
}
}
Slide 8/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Java stack information for the threads listed above:
===================================================
"Thread-0":
at a.ConnectionManager.unregister(Sample.java:20)
- waiting to lock <0x0000000795b8ee60> (a a.ConnectionManager)
at a.ConnectionImpl.close(Sample.java:45)
- locked <0x0000000795d72fd8> (a a.ConnectionImpl)
at a.StressTest.lambda$test$0(StressTest.java:16)
at a.StressTest$$Lambda$1/1297685781.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
"main":
at a.ConnectionImpl.close(Sample.java:44)
- waiting to lock <0x0000000795d72fd8> (a a.ConnectionImpl)
at a.ConnectionManager.closeAll(Sample.java:29)
- locked <0x0000000795b8ee60> (a a.ConnectionManager)
at a.StressTest.test(StressTest.java:21) <27 internal calls>
Found 1 deadlock.
Slide 9/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ConnectionManager cm
Connection con
1 MONITORENTER con
2 con.close()
5 MONITORENTER cm
6 cm.unregister(con)
3 MONITORENTER cm
4 cm.closeAll()
7 MONITORENTER con
8 con.close()
Slide 10/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ConnectionManager cm
Connection con
1 MONITORENTER con
2 con.close()
5 MONITORENTER cm
6 cm.unregister(con)
3 MONITORENTER cm
4 cm.closeAll()
7 MONITORENTER con
8 con.close()
Slide 11/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ConnectionManager cm
Connection con
1 MONITORENTER con
2 con.close()
5 MONITORENTER cm
6 cm.unregister(con)
3 MONITORENTER cm
4 cm.closeAll()
7 MONITORENTER con
8 con.close()
Slide 12/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ConnectionManager cm
Connection con
1 MONITORENTER con
2 con.close()
5 MONITORENTER cm
6 cm.unregister(con)
3 MONITORENTER cm
4 cm.closeAll()
7 MONITORENTER con
8 con.close()
Slide 13/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ConnectionManager cm
Connection con
1 MONITORENTER con
2 con.close()
5 MONITORENTER cm
6 cm.unregister(con)
3 MONITORENTER cm
4 cm.closeAll()
7 MONITORENTER con
8 con.close()
Slide 14/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ConnectionManager cm
Connection con
1 MONITORENTER con
2 con.close()
5 MONITORENTER cm
6 cm.unregister(con)
3 MONITORENTER cm
4 cm.closeAll()
7 MONITORENTER con
8 con.close()
Slide 15/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ConnectionManager cm
Connection con
1 MONITORENTER con
2 con.close()
5 MONITORENTER cm
6 cm.unregister(con)
3 MONITORENTER cm
4 cm.closeAll()
7 MONITORENTER con
8 con.close()
HERE IS A
DEADLOCK!
Slide 16/101. Copyright © 2017. Devexperts LLC. All rights reserved.
JEEConf 2017 - How to find deadlock not getting into it
Program analysis approaches
• Static analysis
• Model checking
• Dynamic analysis
Slide 18/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Dynamic analysis: techniques
• Collecting execution traces (off-line)
- JCarder, MulticoreSDK
• Detection immediately (on-line)
- All context information is available
• Stacktrace, internal state
- VisualThreads
Slide 19/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ALGORITHM
Lock hierarchy
Any two locks should be acquired in the same order in
the same thread
void transfer(Account from, Account to, int amount) {
lock(from)
lock(to)
// Do transfer
unlock(from, to)
}
Slide 21/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock hierarchy
Any two locks should be acquired in the same order in
the same thread
void transfer(Account from, Account to, int amount) {
// Order lock acquisitions by ids
if (from.id < to.id)
lock(from, to)
else
lock(to, from)
// Do transfer
unlock(from, to)
}
Slide 22/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Potential deadlock
• Lock hierarchy compliance – primary method to
avoid deadlocks
• Potential deadlock – this hierarchy violation
Slide 23/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock graph
• Directed graph
• Vertex ↔ lock
• Edge 𝒂, 𝒃 means that 𝒂 is acquired before 𝒃
•Cycle = potential deadlock
Slide 24/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock graph: example
Thread 1 Thread 2
1 a.lock()
2 b.lock()
3 unlock(a, b)
4 b.lock()
5 a.lock()
6 unlock(a, b)
Slide 25/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock graph: example
Thread 1 Thread 2
1 a.lock()
2 b.lock()
3 unlock(a, b)
4 b.lock()
5 a.lock()
6 unlock(a, b)
Slide 26/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock graph: example
Thread 1 Thread 2
1 a.lock()
2 b.lock()
3 unlock(a, b)
4 b.lock()
5 a.lock()
6 unlock(a, b)
Slide 27/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock graph: example
Thread 1 Thread 2
1 a.lock()
2 b.lock()
3 unlock(a, b)
4 b.lock()
5 a.lock()
6 unlock(a, b)
Slide 28/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock graph: example
Thread 1 Thread 2
1 a.lock()
2 b.lock()
3 unlock(a, b)
4 b.lock()
5 a.lock()
6 unlock(a, b)
Slide 29/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock graph: example
Thread 1 Thread 2
1 a.lock()
2 b.lock()
3 unlock(a, b)
4 b.lock()
5 a.lock()
6 unlock(a, b)
Slide 30/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Minimization principle: problem
• Two cycles may refer to the same error
Thread 1 Thread 2
1 a.lock()
2 c.lock()
3 b.lock()
4 unlock(a,b,c)
5 b.lock()
6 a.lock()
7 unlock(a,b)
Slide 31/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Minimization principle: problem (1)
Thread 1 Thread 2
1 a.lock()
2 c.lock()
3 b.lock()
4 unlock(a,b,c)
5 b.lock()
6 a.lock()
7 unlock(a,b)
• Two cycles may refer to the same error
Slide 32/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Minimization principle: problem (2)
• Two cycles may refer to the same error
Thread 1 Thread 2
1 a.lock()
2 c.lock()
3 b.lock()
4 unlock(a,b,c)
5 b.lock()
6 a.lock()
7 unlock(a,b)
Slide 33/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Minimization principle: problem (3)
• Two cycles may refer to the same error
Thread 1 Thread 2
1 a.lock()
2 c.lock()
3 b.lock()
4 unlock(a,b,c)
5 b.lock()
6 a.lock()
7 unlock(a,b)
Slide 34/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Minimization principle: problem (4)
• Two cycles may refer to the same error
Thread 1 Thread 2
1 a.lock()
2 c.lock()
3 b.lock()
4 unlock(a,b,c)
5 b.lock()
6 a.lock()
7 unlock(a,b)
Slide 35/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Minimization principle: problem (5)
• Two cycles may refer to the same error
Thread 1 Thread 2
1 a.lock()
2 c.lock()
3 b.lock()
4 unlock(a,b,c)
5 b.lock()
6 a.lock()
7 unlock(a,b)
Slide 36/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Minimization principle: problem (6)
• Two cycles may refer to the same error
Thread 1 Thread 2
1 a.lock()
2 c.lock()
3 b.lock()
4 unlock(a,b,c)
5 b.lock()
6 a.lock()
7 unlock(a,b)
Slide 37/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Minimization principle
•Shorter cycle is more useful
•Notify about the shortest one only
Slide 38/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Algorithm layout
• Capture lock acquire and release operations
• On lock acquisition:
- Add lock to the set of locks held by the current thread
- Add new edges to the lock graph
- Report new cycles
• On lock release:
- Remove lock from the set of held locks
Slide 39/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Thread#1Thread#2Slide 40/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (1)
Thread#1Thread#2
b
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 41/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (2)
Thread#1Thread#2
b
a
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 42/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (3)
Thread#1Thread#2
b
a
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 43/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (4)
Thread#1Thread#2
b
a
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 44/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (5)
Thread#1Thread#2
b
a
c
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 45/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (6)
Thread#1Thread#2
a
c
b
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 46/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (7)
Thread#1Thread#2
a
c
b
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 47/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (8)
Thread#1Thread#2
a
c
b
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 48/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (9)
Thread#2Thread#1
c
b
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 49/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Lock acquisition and release analysis (10)
Thread#1Thread#2
b
Thread 1 Thread 2
4 a.lock()
5 c.lock()
7 b.lock()
8 a.unlock()
9 c.unlock()
10 b.unlock()
1 b.lock()
2 a.lock()
3 a.unlock()
6 b.unlock()
Slide 50/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Set of held locks
• Common lock usage patterns
synchronized(o) {
// Do something
}
synchronized void f() {
// Do something
}
l.lock()
try {
// Do something
} finally {
l.unlock()
}
• Locks are acquired and released in LIFO (stack) order
Slide 51/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Set of held locks
• Stack with possibility of removing from the middle
• Commonly works in 𝑂 1
• Works in 𝑂(𝐵) at worst
- 𝐵 – number of locks acquired by the current thread
Slide 52/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Topological order
• Constructed by the edges of the directed graph
• No topological order ⇔ graph has a cycle
Slide 53/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Topological order
• Constructed by the edges of the directed graph
• No topological order ⇔ graph has a cycle
Slide 54/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Topological order
• The acyclic part of the lock graph is to be kept
• Edge (𝒂, 𝒃) leads to a topological order violation ⇒
the shortest path 𝒃 ↝ 𝒂 refers to the shortest cycle
• Incremental maintenance
- MNR algorithm suggested by Marchetti-Spaccamela et al.
Slide 55/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: cycle minimization
void transfer(Account from,
Account to,
int amount) {
from.lock()
to.lock()
// Do transfer
unlock(from, to)
}
1 transfer(a, c, …)
2 transfer(c, b, …)
3 transfer(b, a, …)
4 transfer(a, b, …)
Slide 56/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: cycle minimization (1)
void transfer(Account from,
Account to,
int amount) {
from.lock()
to.lock()
// Do transfer
unlock(from, to)
}
1 transfer(a, c, …)
2 transfer(c, b, …)
3 transfer(b, a, …)
4 transfer(a, b, …)
Slide 57/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: cycle minimization (2)
void transfer(Account from,
Account to,
int amount) {
from.lock()
to.lock()
// Do transfer
unlock(from, to)
}
1 transfer(a, c, …)
2 transfer(c, b, …)
3 transfer(b, a, …)
4 transfer(a, b, …)
Slide 58/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: cycle minimization (3)
void transfer(Account from,
Account to,
int amount) {
from.lock()
to.lock()
// Do transfer
unlock(from, to)
}
1 transfer(a, c, …)
2 transfer(c, b, …)
3 transfer(b, a, …)
4 transfer(a, b, …)
Slide 59/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: cycle minimization (4)
void transfer(Account from,
Account to,
int amount) {
from.lock()
to.lock()
// Do transfer
unlock(from, to)
}
1 transfer(a, c, …)
2 transfer(c, b, …)
3 transfer(b, a, …)
4 transfer(a, b, …)
Slide 60/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: cycle minimization
• Adding edge (𝑎, 𝑏) creates new cycle
• Minimization of 𝑏, … , 𝑎 ⇔ minimization of 𝑏 ↝ 𝑎
- Can be implemented with the help of BFS
• Usually 2 or 3 vertexes in cycle
• Current implementation doesn’t support minimization
Slide 61/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: independent cycles
• Logically independent cycles:
- 𝑎, 𝑐, 𝑏
- 𝑎, 𝑏
• Independent cycle is ignored due to minimization principle
• One useful cycle is better 
Slide 62/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: single threaded cycle
Lock a, b
1 a.lock()
2 b.lock()
3 unlock(a, b)
4 b.lock()
5 a.lock()
6 unlock(a, b)
Slide 63/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Limitation: guarded cycle
Thread 1 Thread 2
1 g.lock()
2 a.lock()
3 b.lock()
4 unlock(a, b)
5 g.unlock()
6 g.lock()
7 b.lock()
8 a.lock()
9 unlock(a, b)
10 g.unlock()
Slide 64/101. Copyright © 2017. Devexperts LLC. All rights reserved.
IMPLEMENTATION
Dl-Check
• https://github.com/Devexperts/dlcheck
• Handy for testing
- Throws an exception if -Ddlcheck.fail=true
- Or write your own behavior
• Implemented as a Java agent
- java -javaagent:dlcheck.jar -jar your_app.jar
- Modifies byte-code within ASM framework
Slide 66/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Byte-code transformation
Lock acquisition and release analysis:
• The first and the last action in synchronized method
• MONITORENTER and MONITOREXIT instructions
• java.util.concurrent.locks.Lock
- Method lock
- Successful invocation of method tryLock
- Method unlock
Slide 67/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Synchronized method: in simple terms
synchronized void f() {
// Do something
}
synchronized void f() {
onLockAcquire(this,
2 /*location id*/);
try {
// Do something
} finally {
onLockRelease(this);
}
}
Lock acquisition analysis
Lock release analysis
Slide 68/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Synchronized method: in simple terms
synchronized void f() {
// Do something
}
synchronized void g() {
onLockAcquire(this,
2 /*location id*/);
try {
// Do something
} finally {
onLockRelease(this);
}
}
Lock acquisition analysis
Lock release analysis
What about…
exceptions?
Slide 69/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Synchronized method: exception
synchronized void f() {
onLockAcquire(this, 2);
try {
// Do something
} finally {
onLockRelease(this);
}
}
synchronized void f() {
try {
onLockAcquire(this, 2);
// Do something
} finally {
onLockRelease(this);
}
}
WRONG CORRECT
Slide 70/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Synchronized method: byte-code
synchronized void g();
Code:
0: aload_0 // this
1: iconst_2 // location id
2: invokestatic #22 // onLockAcquire
// Do something
5: aload_0 // this
6: invokestatic #26 // onLockRelease
9: return
10: aload_0 // this
11: invokestatic #26 // onLockRelease
14: athrow
Exception table:
from to target type
0 9 10 any
Lock acquisition analysis
Lock release analysis
synchronized void g() {
try {
onLockAcquire(this, 2);
// Do something
} finally {
onLockRelease(this);
}
}
Slide 71/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Synchronized block
void f() {
synchronized (o) {
// Do something
}
}
Lock acquisition analysis
Lock release analysis
void f() {
MONITORENTER o
try {
// Do something
} finally {
MONITOREXIT o
}
}
void f() {
MONITORENTER o
try {
onLockAcquire(o, 42);
// Do something
} finally {
MONITOREXIT o
onLockRelease(o);
}
}
Slide 72/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Synchronized block
void f() {
synchronized (o) {
// Do something
}
}
Анализ взятия блокировки
Анализ отпускания блокировки
void f() {
MONITORENTER o
try {
// Do something
} finally {
MONITOREXIT o
}
}
void f() {
MONITORENTER o
try {
onLockAcquire(o, 42);
// Do something
} finally {
MONITOREXIT o
onLockRelease(o);
}
}
Not so
simple!
Slide 73/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Synchronized block: backstage
void f() {
synchronized (o) {
// Do something
}
}
void f();
Code:
0: aload_0 // this
1: getfield #2 // monitor
4: dup
5: astore_1 // store monitor
6: monitorenter
// Do something
7: aload_1 // monitor
8: monitorexit
9: goto 17 // skip finally
12: astore_2 // exception
13: aload_1 // monitor
14: monitorexit
15: aload_2 // exception
16: athrow
17: return
Exception table:
from to target type
7 9 12 any
12 15 12 any trycatch
Slide 74/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Synchronized block: exception
void f() {
MONITORENTER o
try {
onLockAcquire(o, 42);
// Do something
} finally {
MONITOREXIT o
try {
onLockRelease(o);
catch (Throwable t) {}
}
}
void f() {
MONITORENTER o
try {
onLockAcquire(o, 42);
// Do something
} finally {
MONITOREXIT o
onLockRelease(o);
}
}
WRONG CORRECT
Slide 75/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Slide 76/101. Copyright © 2017. Devexperts LLC. All rights reserved.
void f() {
MONITORENTER o
try {
onLockAcquire(o, 42);
} catch (Throwable t) {
MONITOREXIT o
onLockRelease(o);
throw t;
}
try {
// Do something
...
Synchronized block: not a block
void f() {
MONITORENTER o
try {
// Do something
} finally {
MONITOREXIT o
}
}
Addtry-catch
Slide 77/101. Copyright © 2017. Devexperts LLC. All rights reserved.
j.u.c.l.Lock: common usages
void g() {
l.lock();
// Do something
l.unlock();
}
void f() {
l.lock();
try {
// Do something
} finally {
l.unlock();
}
}
void h() {
b = l.tryLock();
// Do something
l.unlock();
}
Slide 78/101. Copyright © 2017. Devexperts LLC. All rights reserved.
j.u.c.l.Lock: general usages
void g() {
l.lock();
// Do something
l.unlock();
}
void f() {
l.lock();
try {
// Do something
} finally {
l.unlock();
}
}
void h() {
b = l.tryLock();
// Do something
l.unlock();
}
It looks like unpaired
MONITORENTER
and MONITOREXIT!
Slide 79/101. Copyright © 2017. Devexperts LLC. All rights reserved.
j.u.c.l.Lock: tryLock
void h() {
b = l.tryLock();
// Do something
l.unlock();
}
void h() {
b = l.tryLock();
if (b) {
try {
onLockAcquire(l, 2);
} catch (Throwable t) {
l.unlock();
onLockRelease(l);
throw t;
}
}
// Do something
l.unlock();
onLockRelease(l);
}
Slide 80/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ClassTransformer
Code template:
public final byte[] transform(..., classFileBuffer) {
ClassReader cr = new ClassReader(classFileBuffer);
ClassWriter cw = new ClassWriter(...);
ClassVisitor classTransformer = new MyTransformer(cw, ...);
cr.accept(classTransformer, EXPAND_FRAMES);
return cw.toByteArray();
}
Let’s try to run…
Slide 81/101. Copyright © 2017. Devexperts LLC. All rights reserved.
ClassTransformer: LinkageError
java.lang.LinkageError: loader (instance of
sun/misc/Launcher$AppClassLoader): attempted duplicate class
definition for name: "com/intellij/util/lang/UrlClassLoader"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
...
Slide 82/101. Copyright © 2017. Devexperts LLC. All rights reserved.
java.lang.LinkageError: loader (instance of
sun/misc/Launcher$AppClassLoader): attempted duplicate class
definition for name: "com/intellij/util/lang/UrlClassLoader"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
...
ClassTransformer: LinkageError
F***ing
ASM!
Slide 83/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Problem ClassWriter
protected String getCommonSuperClass(String type1,
String type2) {
Class<?> c1, c2;
ClassLoader loader = getClass().getClassLoader();
try {
c1 = Class.forName(type1.replace('/', '.'), false, loader);
c2 = Class.forName(type2.replace('/', '.'), false, loader);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (c1.isAssignableFrom(c2))
return type1;
...
Slide 84/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Write it yourself!
@Override
protected String getCommonSuperClass(String type1,
String type2) {
ClassInfo c = ciCache.getOrBuildClassInfo(type1, loader);
ClassInfo d = ciCache.getOrBuildClassInfo(type2, loader);
if (c.isAssignableFrom(d, ciCache, loader))
return type1;
if (d.isAssignableFrom(c, ciCache, loader))
return type2;
...
ClassInfo is available BEFORE transformation
Slide 85/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Hooray! It works!
JAgent framework
• This problem is solved in JAgent
- https://github.com/Devexperts/jagent
• Makes java agents writing more simple
Slide 87/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Dependencies conflict
• Several agents are used:
java -javaagent:agent1.jar -javaagent:agent2.jar
–jar my_app.jar
ASM 3 ASM 4
• Dependencies should be isolated
Slide 88/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Isolation techniques
• Repackaging
- maven-shade-plugin (or analogue)
- Needs to know transitive dependencies and their
structure
- Sometimes doesn’t work as well (reflection)
• Separate ClassLoader
- Cannot be used for injected code
Slide 89/101. Copyright © 2017. Devexperts LLC. All rights reserved.
JAgent will help us
JAgent API
core:
+ premain
+ runtime
code
External libraries
JAgent Impl
transformer:
transformation
code
External libraries
Runs transformation
code via JAgent API
Inserts new code
JAgent ClassLoaderSystem ClassLoader
Slide 90/101. Copyright © 2017. Devexperts LLC. All rights reserved.
EVALUATION
Benchmarks
• SpecJVM2008: Apache Derby (4 and 40 threads)
• DaCapo: Apache Lucene
• DaCapo: Banking application
• …
Slide 92/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Performance impact
9.7
128.2
1.25
2.6
7.3
120.71
40.33
3.25
1
2
4
8
16
32
64
128
Derby 4T Derby 40T Lucene Bank
SLOWDOWNFACTOR
Jcarder MulticoreSDK
Slide 93/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Performance impact
1.53 1.76
1.03
2.6
9.7
128.2
1.25
2.6
7.3
120.71
40.33
3.25
1
2
4
8
16
32
64
128
Derby 4T Derby 40T Lucene Bank
SLOWDOWNFACTOR
Dl-Check Jcarder MulticoreSDK
Slide 94/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Memory usage impact
1
1.07 1.06 1
0.61
1.22
1 1
0.74
1.12
1.35
1
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
Derby 4 Derby 40T Lucene Bank
INCREASEFACTOR
Dl-Check Jcarder MulticoreSDK
Slide 95/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Real-life
example
Slide 96/101. Copyright © 2017. Devexperts LLC. All rights reserved.
public void testClose() {
cm.register(con);
// lock cm
// lock con for con.onRegister()
assertEquals(1, cm.getConCount());
con.close();
// lock con
// lock cm for cm.unregister()
assertEquals(0, cm.getConCount());
}
Slide 97/101. Copyright © 2017. Devexperts LLC. All rights reserved.
==========================
!!! Potential deadlock !!!
==========================
### Cycle in lock graph: ###
Lock ConnectionImpl@d70c109 was acquired at:
a.ConnectionImpl.onRegister(Sample.java:39)
a.ConnectionImpl.close(Sample.java:44)
Lock ConnectionManager@2be94b0f was acquired at:
a.ConnectionManager.getConCount(Sample.java:24)
a.ConnectionManager.register(Sample.java:15)
a.ConnectionManager.unregister(Sample.java:20)
### Current lock stack: ###
Lock ConnectionImpl@d70c109 was acquired at:
a.ConnectionImpl.onRegister(Sample.java:39)
a.ConnectionImpl.close(Sample.java:44)
### Current stacktrace: ###
a.ConnectionManager.unregister(Sample.java:20)
a.ConnectionImpl.close(Sample.java:45)
a.FunctionalityTest.testClose(FunctionalityTest.java:22)
...
Slide 98/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Evaluation in real projects
• Internal projects
• IntelliJ IDEA
• Kotlin
• …
Slide 99/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Summary
• On-line algorithm for detecting potential deadlocks
• JAgent framework for writing Java agents
- https://github.com/Devexperts/jagent
• Dl-Check tool has been implemented
- https://github.com/Devexperts/dlcheck
• Further work:
- Contracts to describe lock acquisition rules
Slide 100/101. Copyright © 2017. Devexperts LLC. All rights reserved.
Thank you for attention!
Nikita Koval, Devexperts LLC
nkoval@devexperts.com
twitter.com/nkoval_

More Related Content

PDF
Deterministic simulation testing
PDF
TMPA-2017: Dl-Check: Dynamic Potential Deadlock Detection Tool for Java Programs
PDF
PVS-Studio in 2021 - Error Examples
PDF
Concurrency Concepts in Java
PPTX
How Data Flow analysis works in a static code analyzer
PDF
Introduction to web programming for java and c# programmers by @drpicox
PDF
Non-blocking synchronization — what is it and why we (don't?) need it
PPTX
Navigating the xDD Alphabet Soup
Deterministic simulation testing
TMPA-2017: Dl-Check: Dynamic Potential Deadlock Detection Tool for Java Programs
PVS-Studio in 2021 - Error Examples
Concurrency Concepts in Java
How Data Flow analysis works in a static code analyzer
Introduction to web programming for java and c# programmers by @drpicox
Non-blocking synchronization — what is it and why we (don't?) need it
Navigating the xDD Alphabet Soup

What's hot (20)

PDF
Software Testing - Invited Lecture at UNSW Sydney
PDF
JVM Mechanics: Understanding the JIT's Tricks
PDF
Gabriele Petronella - FP for front-end development: should you care? - Codemo...
PDF
Non-blocking Michael-Scott queue algorithm
PPTX
Testability for Developers
PDF
José Selvi - Historia de un CryptoFAIL [rootedvlc4]
PDF
Changes and Bugs: Mining and Predicting Development Activities
PPTX
SAST and Application Security: how to fight vulnerabilities in the code
PDF
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
PDF
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
PDF
Java 7 LavaJUG
PDF
Multithreading done right
PPTX
Dealing with combinatorial explosions and boring tests
PDF
Checking VirtualDub
PDF
關於測試,我說的其實是......
PPTX
Tokyo APAC Groundbreakers tour - The Complete Java Developer
PDF
Tools and Techniques for Understanding Threading Behavior in Android
PPT
Dac07
PDF
The Ring programming language version 1.5.3 book - Part 89 of 184
PDF
Testing a 2D Platformer with Spock
Software Testing - Invited Lecture at UNSW Sydney
JVM Mechanics: Understanding the JIT's Tricks
Gabriele Petronella - FP for front-end development: should you care? - Codemo...
Non-blocking Michael-Scott queue algorithm
Testability for Developers
José Selvi - Historia de un CryptoFAIL [rootedvlc4]
Changes and Bugs: Mining and Predicting Development Activities
SAST and Application Security: how to fight vulnerabilities in the code
Java 7 Launch Event at LyonJUG, Lyon France. Fork / Join framework and Projec...
OracleCode One 2018: Java 5, 6, 7, 8, 9, 10, 11: What Did You Miss?
Java 7 LavaJUG
Multithreading done right
Dealing with combinatorial explosions and boring tests
Checking VirtualDub
關於測試,我說的其實是......
Tokyo APAC Groundbreakers tour - The Complete Java Developer
Tools and Techniques for Understanding Threading Behavior in Android
Dac07
The Ring programming language version 1.5.3 book - Part 89 of 184
Testing a 2D Platformer with Spock
Ad

Similar to JEEConf 2017 - How to find deadlock not getting into it (20)

ODP
Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...
PPT
Dead locks9cm604.39
PDF
Comparing different concurrency models on the JVM
PPTX
Concurrency
PPTX
Thread & concurrancy
ODP
Concurrent Programming in Java
ODP
Java Concurrency, Memory Model, and Trends
PDF
Concurrency: Best Practices
PDF
Concurrency on the JVM
PDF
Thread Dump Analysis
PDF
Threads and Java Memory Model Explained
PPTX
Concurrency in Eclipse: Best Practices and Gotchas
PDF
Java synchronizers
PPTX
Threading in java - a pragmatic primer
PPTX
Concurrency with java
PPTX
Concurrency with java
PPTX
Concurrency with java
PPTX
Concurrency with java
PPTX
Concurrency with java
PPTX
Concurrency with java
Mario Fusco - Comparing different concurrency models on the JVM | Codemotion ...
Dead locks9cm604.39
Comparing different concurrency models on the JVM
Concurrency
Thread & concurrancy
Concurrent Programming in Java
Java Concurrency, Memory Model, and Trends
Concurrency: Best Practices
Concurrency on the JVM
Thread Dump Analysis
Threads and Java Memory Model Explained
Concurrency in Eclipse: Best Practices and Gotchas
Java synchronizers
Threading in java - a pragmatic primer
Concurrency with java
Concurrency with java
Concurrency with java
Concurrency with java
Concurrency with java
Concurrency with java
Ad

Recently uploaded (20)

PDF
Chinmaya Tiranga quiz Grand Finale.pdf
PPTX
Pharma ospi slides which help in ospi learning
PDF
Trump Administration's workforce development strategy
PDF
Computing-Curriculum for Schools in Ghana
PPTX
human mycosis Human fungal infections are called human mycosis..pptx
PDF
OBE - B.A.(HON'S) IN INTERIOR ARCHITECTURE -Ar.MOHIUDDIN.pdf
DOC
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
PDF
Microbial disease of the cardiovascular and lymphatic systems
PPTX
GDM (1) (1).pptx small presentation for students
PDF
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
PPTX
Tissue processing ( HISTOPATHOLOGICAL TECHNIQUE
PPTX
Microbial diseases, their pathogenesis and prophylaxis
PDF
Complications of Minimal Access Surgery at WLH
PPTX
Cell Structure & Organelles in detailed.
PDF
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
PDF
Yogi Goddess Pres Conference Studio Updates
PDF
Classroom Observation Tools for Teachers
PPTX
Lesson notes of climatology university.
PDF
Abdominal Access Techniques with Prof. Dr. R K Mishra
PDF
FourierSeries-QuestionsWithAnswers(Part-A).pdf
Chinmaya Tiranga quiz Grand Finale.pdf
Pharma ospi slides which help in ospi learning
Trump Administration's workforce development strategy
Computing-Curriculum for Schools in Ghana
human mycosis Human fungal infections are called human mycosis..pptx
OBE - B.A.(HON'S) IN INTERIOR ARCHITECTURE -Ar.MOHIUDDIN.pdf
Soft-furnishing-By-Architect-A.F.M.Mohiuddin-Akhand.doc
Microbial disease of the cardiovascular and lymphatic systems
GDM (1) (1).pptx small presentation for students
grade 11-chemistry_fetena_net_5883.pdf teacher guide for all student
Tissue processing ( HISTOPATHOLOGICAL TECHNIQUE
Microbial diseases, their pathogenesis and prophylaxis
Complications of Minimal Access Surgery at WLH
Cell Structure & Organelles in detailed.
3rd Neelam Sanjeevareddy Memorial Lecture.pdf
Yogi Goddess Pres Conference Studio Updates
Classroom Observation Tools for Teachers
Lesson notes of climatology university.
Abdominal Access Techniques with Prof. Dr. R K Mishra
FourierSeries-QuestionsWithAnswers(Part-A).pdf

JEEConf 2017 - How to find deadlock not getting into it

  • 1. How to find deadlock not getting into it Nikita Koval, Devexperts LLC nkoval@devexperts.com twitter.com/nkoval_
  • 2. Other tracks are more interesting! https://github.com/Devexperts/dlcheck Slide 2/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 3. Real-life example Slide 3/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 4. interface Con { // Connection void onRegister(ConnectionManager cm); void close(); } class ConnectionManager { Set<Con> cons = new HashSet<>(); synchronized void register(Con c) { cons.add(c); con.onRegister(this); } synchronized void unregister(Con c) { cons.remove(c); } ... Slide 4/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 5. interface Con { // Connection void onRegister(ConnectionManager cm); void close(); } class ConnectionManager { Set<Con> cons = new HashSet<>(); synchronized void register(Con c) { cons.add(c); con.onRegister(this); } synchronized void unregister(Con c) { cons.remove(c); } ... // ... ConnectionManager synchronized int getConCount() { return cons.size(); } synchronized void closeAll() { for (Con c: cons) c.close(); } } Slide 5/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 6. class ConnectionImpl implements Con { ConnectionManager cm; @Override public synchronized void onRegister(ConnectionManager cm) { this.cm = cm; } @Override public synchronized void close() { if (cm != null) { cm.unregister(this); cm = null; } } } Slide 6/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 7. Run functional test… Works well! Run stress test… Slide 7/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 8. public void test() throws Exception { ConnectionManager cm = new ConnectionManager(); new Thread(() -> { while (true) { Connection con = new ConnectionImpl(); cm.register(con); con.close(); // lock con -> lock cm } }).start(); for (int i = 1; i < 100_000; i++) { System.out.println("Iteration #" + i); cm.closeAll(); // lock cm -> lock con } } Slide 8/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 9. Java stack information for the threads listed above: =================================================== "Thread-0": at a.ConnectionManager.unregister(Sample.java:20) - waiting to lock <0x0000000795b8ee60> (a a.ConnectionManager) at a.ConnectionImpl.close(Sample.java:45) - locked <0x0000000795d72fd8> (a a.ConnectionImpl) at a.StressTest.lambda$test$0(StressTest.java:16) at a.StressTest$$Lambda$1/1297685781.run(Unknown Source) at java.lang.Thread.run(Thread.java:745) "main": at a.ConnectionImpl.close(Sample.java:44) - waiting to lock <0x0000000795d72fd8> (a a.ConnectionImpl) at a.ConnectionManager.closeAll(Sample.java:29) - locked <0x0000000795b8ee60> (a a.ConnectionManager) at a.StressTest.test(StressTest.java:21) <27 internal calls> Found 1 deadlock. Slide 9/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 10. ConnectionManager cm Connection con 1 MONITORENTER con 2 con.close() 5 MONITORENTER cm 6 cm.unregister(con) 3 MONITORENTER cm 4 cm.closeAll() 7 MONITORENTER con 8 con.close() Slide 10/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 11. ConnectionManager cm Connection con 1 MONITORENTER con 2 con.close() 5 MONITORENTER cm 6 cm.unregister(con) 3 MONITORENTER cm 4 cm.closeAll() 7 MONITORENTER con 8 con.close() Slide 11/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 12. ConnectionManager cm Connection con 1 MONITORENTER con 2 con.close() 5 MONITORENTER cm 6 cm.unregister(con) 3 MONITORENTER cm 4 cm.closeAll() 7 MONITORENTER con 8 con.close() Slide 12/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 13. ConnectionManager cm Connection con 1 MONITORENTER con 2 con.close() 5 MONITORENTER cm 6 cm.unregister(con) 3 MONITORENTER cm 4 cm.closeAll() 7 MONITORENTER con 8 con.close() Slide 13/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 14. ConnectionManager cm Connection con 1 MONITORENTER con 2 con.close() 5 MONITORENTER cm 6 cm.unregister(con) 3 MONITORENTER cm 4 cm.closeAll() 7 MONITORENTER con 8 con.close() Slide 14/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 15. ConnectionManager cm Connection con 1 MONITORENTER con 2 con.close() 5 MONITORENTER cm 6 cm.unregister(con) 3 MONITORENTER cm 4 cm.closeAll() 7 MONITORENTER con 8 con.close() Slide 15/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 16. ConnectionManager cm Connection con 1 MONITORENTER con 2 con.close() 5 MONITORENTER cm 6 cm.unregister(con) 3 MONITORENTER cm 4 cm.closeAll() 7 MONITORENTER con 8 con.close() HERE IS A DEADLOCK! Slide 16/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 18. Program analysis approaches • Static analysis • Model checking • Dynamic analysis Slide 18/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 19. Dynamic analysis: techniques • Collecting execution traces (off-line) - JCarder, MulticoreSDK • Detection immediately (on-line) - All context information is available • Stacktrace, internal state - VisualThreads Slide 19/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 21. Lock hierarchy Any two locks should be acquired in the same order in the same thread void transfer(Account from, Account to, int amount) { lock(from) lock(to) // Do transfer unlock(from, to) } Slide 21/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 22. Lock hierarchy Any two locks should be acquired in the same order in the same thread void transfer(Account from, Account to, int amount) { // Order lock acquisitions by ids if (from.id < to.id) lock(from, to) else lock(to, from) // Do transfer unlock(from, to) } Slide 22/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 23. Potential deadlock • Lock hierarchy compliance – primary method to avoid deadlocks • Potential deadlock – this hierarchy violation Slide 23/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 24. Lock graph • Directed graph • Vertex ↔ lock • Edge 𝒂, 𝒃 means that 𝒂 is acquired before 𝒃 •Cycle = potential deadlock Slide 24/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 25. Lock graph: example Thread 1 Thread 2 1 a.lock() 2 b.lock() 3 unlock(a, b) 4 b.lock() 5 a.lock() 6 unlock(a, b) Slide 25/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 26. Lock graph: example Thread 1 Thread 2 1 a.lock() 2 b.lock() 3 unlock(a, b) 4 b.lock() 5 a.lock() 6 unlock(a, b) Slide 26/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 27. Lock graph: example Thread 1 Thread 2 1 a.lock() 2 b.lock() 3 unlock(a, b) 4 b.lock() 5 a.lock() 6 unlock(a, b) Slide 27/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 28. Lock graph: example Thread 1 Thread 2 1 a.lock() 2 b.lock() 3 unlock(a, b) 4 b.lock() 5 a.lock() 6 unlock(a, b) Slide 28/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 29. Lock graph: example Thread 1 Thread 2 1 a.lock() 2 b.lock() 3 unlock(a, b) 4 b.lock() 5 a.lock() 6 unlock(a, b) Slide 29/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 30. Lock graph: example Thread 1 Thread 2 1 a.lock() 2 b.lock() 3 unlock(a, b) 4 b.lock() 5 a.lock() 6 unlock(a, b) Slide 30/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 31. Minimization principle: problem • Two cycles may refer to the same error Thread 1 Thread 2 1 a.lock() 2 c.lock() 3 b.lock() 4 unlock(a,b,c) 5 b.lock() 6 a.lock() 7 unlock(a,b) Slide 31/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 32. Minimization principle: problem (1) Thread 1 Thread 2 1 a.lock() 2 c.lock() 3 b.lock() 4 unlock(a,b,c) 5 b.lock() 6 a.lock() 7 unlock(a,b) • Two cycles may refer to the same error Slide 32/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 33. Minimization principle: problem (2) • Two cycles may refer to the same error Thread 1 Thread 2 1 a.lock() 2 c.lock() 3 b.lock() 4 unlock(a,b,c) 5 b.lock() 6 a.lock() 7 unlock(a,b) Slide 33/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 34. Minimization principle: problem (3) • Two cycles may refer to the same error Thread 1 Thread 2 1 a.lock() 2 c.lock() 3 b.lock() 4 unlock(a,b,c) 5 b.lock() 6 a.lock() 7 unlock(a,b) Slide 34/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 35. Minimization principle: problem (4) • Two cycles may refer to the same error Thread 1 Thread 2 1 a.lock() 2 c.lock() 3 b.lock() 4 unlock(a,b,c) 5 b.lock() 6 a.lock() 7 unlock(a,b) Slide 35/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 36. Minimization principle: problem (5) • Two cycles may refer to the same error Thread 1 Thread 2 1 a.lock() 2 c.lock() 3 b.lock() 4 unlock(a,b,c) 5 b.lock() 6 a.lock() 7 unlock(a,b) Slide 36/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 37. Minimization principle: problem (6) • Two cycles may refer to the same error Thread 1 Thread 2 1 a.lock() 2 c.lock() 3 b.lock() 4 unlock(a,b,c) 5 b.lock() 6 a.lock() 7 unlock(a,b) Slide 37/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 38. Minimization principle •Shorter cycle is more useful •Notify about the shortest one only Slide 38/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 39. Algorithm layout • Capture lock acquire and release operations • On lock acquisition: - Add lock to the set of locks held by the current thread - Add new edges to the lock graph - Report new cycles • On lock release: - Remove lock from the set of held locks Slide 39/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 40. Lock acquisition and release analysis Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Thread#1Thread#2Slide 40/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 41. Lock acquisition and release analysis (1) Thread#1Thread#2 b Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 41/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 42. Lock acquisition and release analysis (2) Thread#1Thread#2 b a Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 42/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 43. Lock acquisition and release analysis (3) Thread#1Thread#2 b a Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 43/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 44. Lock acquisition and release analysis (4) Thread#1Thread#2 b a Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 44/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 45. Lock acquisition and release analysis (5) Thread#1Thread#2 b a c Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 45/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 46. Lock acquisition and release analysis (6) Thread#1Thread#2 a c b Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 46/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 47. Lock acquisition and release analysis (7) Thread#1Thread#2 a c b Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 47/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 48. Lock acquisition and release analysis (8) Thread#1Thread#2 a c b Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 48/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 49. Lock acquisition and release analysis (9) Thread#2Thread#1 c b Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 49/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 50. Lock acquisition and release analysis (10) Thread#1Thread#2 b Thread 1 Thread 2 4 a.lock() 5 c.lock() 7 b.lock() 8 a.unlock() 9 c.unlock() 10 b.unlock() 1 b.lock() 2 a.lock() 3 a.unlock() 6 b.unlock() Slide 50/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 51. Set of held locks • Common lock usage patterns synchronized(o) { // Do something } synchronized void f() { // Do something } l.lock() try { // Do something } finally { l.unlock() } • Locks are acquired and released in LIFO (stack) order Slide 51/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 52. Set of held locks • Stack with possibility of removing from the middle • Commonly works in 𝑂 1 • Works in 𝑂(𝐵) at worst - 𝐵 – number of locks acquired by the current thread Slide 52/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 53. Topological order • Constructed by the edges of the directed graph • No topological order ⇔ graph has a cycle Slide 53/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 54. Topological order • Constructed by the edges of the directed graph • No topological order ⇔ graph has a cycle Slide 54/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 55. Topological order • The acyclic part of the lock graph is to be kept • Edge (𝒂, 𝒃) leads to a topological order violation ⇒ the shortest path 𝒃 ↝ 𝒂 refers to the shortest cycle • Incremental maintenance - MNR algorithm suggested by Marchetti-Spaccamela et al. Slide 55/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 56. Limitation: cycle minimization void transfer(Account from, Account to, int amount) { from.lock() to.lock() // Do transfer unlock(from, to) } 1 transfer(a, c, …) 2 transfer(c, b, …) 3 transfer(b, a, …) 4 transfer(a, b, …) Slide 56/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 57. Limitation: cycle minimization (1) void transfer(Account from, Account to, int amount) { from.lock() to.lock() // Do transfer unlock(from, to) } 1 transfer(a, c, …) 2 transfer(c, b, …) 3 transfer(b, a, …) 4 transfer(a, b, …) Slide 57/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 58. Limitation: cycle minimization (2) void transfer(Account from, Account to, int amount) { from.lock() to.lock() // Do transfer unlock(from, to) } 1 transfer(a, c, …) 2 transfer(c, b, …) 3 transfer(b, a, …) 4 transfer(a, b, …) Slide 58/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 59. Limitation: cycle minimization (3) void transfer(Account from, Account to, int amount) { from.lock() to.lock() // Do transfer unlock(from, to) } 1 transfer(a, c, …) 2 transfer(c, b, …) 3 transfer(b, a, …) 4 transfer(a, b, …) Slide 59/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 60. Limitation: cycle minimization (4) void transfer(Account from, Account to, int amount) { from.lock() to.lock() // Do transfer unlock(from, to) } 1 transfer(a, c, …) 2 transfer(c, b, …) 3 transfer(b, a, …) 4 transfer(a, b, …) Slide 60/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 61. Limitation: cycle minimization • Adding edge (𝑎, 𝑏) creates new cycle • Minimization of 𝑏, … , 𝑎 ⇔ minimization of 𝑏 ↝ 𝑎 - Can be implemented with the help of BFS • Usually 2 or 3 vertexes in cycle • Current implementation doesn’t support minimization Slide 61/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 62. Limitation: independent cycles • Logically independent cycles: - 𝑎, 𝑐, 𝑏 - 𝑎, 𝑏 • Independent cycle is ignored due to minimization principle • One useful cycle is better  Slide 62/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 63. Limitation: single threaded cycle Lock a, b 1 a.lock() 2 b.lock() 3 unlock(a, b) 4 b.lock() 5 a.lock() 6 unlock(a, b) Slide 63/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 64. Limitation: guarded cycle Thread 1 Thread 2 1 g.lock() 2 a.lock() 3 b.lock() 4 unlock(a, b) 5 g.unlock() 6 g.lock() 7 b.lock() 8 a.lock() 9 unlock(a, b) 10 g.unlock() Slide 64/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 66. Dl-Check • https://github.com/Devexperts/dlcheck • Handy for testing - Throws an exception if -Ddlcheck.fail=true - Or write your own behavior • Implemented as a Java agent - java -javaagent:dlcheck.jar -jar your_app.jar - Modifies byte-code within ASM framework Slide 66/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 67. Byte-code transformation Lock acquisition and release analysis: • The first and the last action in synchronized method • MONITORENTER and MONITOREXIT instructions • java.util.concurrent.locks.Lock - Method lock - Successful invocation of method tryLock - Method unlock Slide 67/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 68. Synchronized method: in simple terms synchronized void f() { // Do something } synchronized void f() { onLockAcquire(this, 2 /*location id*/); try { // Do something } finally { onLockRelease(this); } } Lock acquisition analysis Lock release analysis Slide 68/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 69. Synchronized method: in simple terms synchronized void f() { // Do something } synchronized void g() { onLockAcquire(this, 2 /*location id*/); try { // Do something } finally { onLockRelease(this); } } Lock acquisition analysis Lock release analysis What about… exceptions? Slide 69/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 70. Synchronized method: exception synchronized void f() { onLockAcquire(this, 2); try { // Do something } finally { onLockRelease(this); } } synchronized void f() { try { onLockAcquire(this, 2); // Do something } finally { onLockRelease(this); } } WRONG CORRECT Slide 70/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 71. Synchronized method: byte-code synchronized void g(); Code: 0: aload_0 // this 1: iconst_2 // location id 2: invokestatic #22 // onLockAcquire // Do something 5: aload_0 // this 6: invokestatic #26 // onLockRelease 9: return 10: aload_0 // this 11: invokestatic #26 // onLockRelease 14: athrow Exception table: from to target type 0 9 10 any Lock acquisition analysis Lock release analysis synchronized void g() { try { onLockAcquire(this, 2); // Do something } finally { onLockRelease(this); } } Slide 71/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 72. Synchronized block void f() { synchronized (o) { // Do something } } Lock acquisition analysis Lock release analysis void f() { MONITORENTER o try { // Do something } finally { MONITOREXIT o } } void f() { MONITORENTER o try { onLockAcquire(o, 42); // Do something } finally { MONITOREXIT o onLockRelease(o); } } Slide 72/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 73. Synchronized block void f() { synchronized (o) { // Do something } } Анализ взятия блокировки Анализ отпускания блокировки void f() { MONITORENTER o try { // Do something } finally { MONITOREXIT o } } void f() { MONITORENTER o try { onLockAcquire(o, 42); // Do something } finally { MONITOREXIT o onLockRelease(o); } } Not so simple! Slide 73/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 74. Synchronized block: backstage void f() { synchronized (o) { // Do something } } void f(); Code: 0: aload_0 // this 1: getfield #2 // monitor 4: dup 5: astore_1 // store monitor 6: monitorenter // Do something 7: aload_1 // monitor 8: monitorexit 9: goto 17 // skip finally 12: astore_2 // exception 13: aload_1 // monitor 14: monitorexit 15: aload_2 // exception 16: athrow 17: return Exception table: from to target type 7 9 12 any 12 15 12 any trycatch Slide 74/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 75. Synchronized block: exception void f() { MONITORENTER o try { onLockAcquire(o, 42); // Do something } finally { MONITOREXIT o try { onLockRelease(o); catch (Throwable t) {} } } void f() { MONITORENTER o try { onLockAcquire(o, 42); // Do something } finally { MONITOREXIT o onLockRelease(o); } } WRONG CORRECT Slide 75/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 76. Slide 76/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 77. void f() { MONITORENTER o try { onLockAcquire(o, 42); } catch (Throwable t) { MONITOREXIT o onLockRelease(o); throw t; } try { // Do something ... Synchronized block: not a block void f() { MONITORENTER o try { // Do something } finally { MONITOREXIT o } } Addtry-catch Slide 77/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 78. j.u.c.l.Lock: common usages void g() { l.lock(); // Do something l.unlock(); } void f() { l.lock(); try { // Do something } finally { l.unlock(); } } void h() { b = l.tryLock(); // Do something l.unlock(); } Slide 78/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 79. j.u.c.l.Lock: general usages void g() { l.lock(); // Do something l.unlock(); } void f() { l.lock(); try { // Do something } finally { l.unlock(); } } void h() { b = l.tryLock(); // Do something l.unlock(); } It looks like unpaired MONITORENTER and MONITOREXIT! Slide 79/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 80. j.u.c.l.Lock: tryLock void h() { b = l.tryLock(); // Do something l.unlock(); } void h() { b = l.tryLock(); if (b) { try { onLockAcquire(l, 2); } catch (Throwable t) { l.unlock(); onLockRelease(l); throw t; } } // Do something l.unlock(); onLockRelease(l); } Slide 80/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 81. ClassTransformer Code template: public final byte[] transform(..., classFileBuffer) { ClassReader cr = new ClassReader(classFileBuffer); ClassWriter cw = new ClassWriter(...); ClassVisitor classTransformer = new MyTransformer(cw, ...); cr.accept(classTransformer, EXPAND_FRAMES); return cw.toByteArray(); } Let’s try to run… Slide 81/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 82. ClassTransformer: LinkageError java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "com/intellij/util/lang/UrlClassLoader" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... Slide 82/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 83. java.lang.LinkageError: loader (instance of sun/misc/Launcher$AppClassLoader): attempted duplicate class definition for name: "com/intellij/util/lang/UrlClassLoader" at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... ClassTransformer: LinkageError F***ing ASM! Slide 83/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 84. Problem ClassWriter protected String getCommonSuperClass(String type1, String type2) { Class<?> c1, c2; ClassLoader loader = getClass().getClassLoader(); try { c1 = Class.forName(type1.replace('/', '.'), false, loader); c2 = Class.forName(type2.replace('/', '.'), false, loader); } catch (Exception e) { throw new RuntimeException(e); } if (c1.isAssignableFrom(c2)) return type1; ... Slide 84/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 85. Write it yourself! @Override protected String getCommonSuperClass(String type1, String type2) { ClassInfo c = ciCache.getOrBuildClassInfo(type1, loader); ClassInfo d = ciCache.getOrBuildClassInfo(type2, loader); if (c.isAssignableFrom(d, ciCache, loader)) return type1; if (d.isAssignableFrom(c, ciCache, loader)) return type2; ... ClassInfo is available BEFORE transformation Slide 85/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 87. JAgent framework • This problem is solved in JAgent - https://github.com/Devexperts/jagent • Makes java agents writing more simple Slide 87/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 88. Dependencies conflict • Several agents are used: java -javaagent:agent1.jar -javaagent:agent2.jar –jar my_app.jar ASM 3 ASM 4 • Dependencies should be isolated Slide 88/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 89. Isolation techniques • Repackaging - maven-shade-plugin (or analogue) - Needs to know transitive dependencies and their structure - Sometimes doesn’t work as well (reflection) • Separate ClassLoader - Cannot be used for injected code Slide 89/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 90. JAgent will help us JAgent API core: + premain + runtime code External libraries JAgent Impl transformer: transformation code External libraries Runs transformation code via JAgent API Inserts new code JAgent ClassLoaderSystem ClassLoader Slide 90/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 92. Benchmarks • SpecJVM2008: Apache Derby (4 and 40 threads) • DaCapo: Apache Lucene • DaCapo: Banking application • … Slide 92/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 93. Performance impact 9.7 128.2 1.25 2.6 7.3 120.71 40.33 3.25 1 2 4 8 16 32 64 128 Derby 4T Derby 40T Lucene Bank SLOWDOWNFACTOR Jcarder MulticoreSDK Slide 93/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 94. Performance impact 1.53 1.76 1.03 2.6 9.7 128.2 1.25 2.6 7.3 120.71 40.33 3.25 1 2 4 8 16 32 64 128 Derby 4T Derby 40T Lucene Bank SLOWDOWNFACTOR Dl-Check Jcarder MulticoreSDK Slide 94/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 95. Memory usage impact 1 1.07 1.06 1 0.61 1.22 1 1 0.74 1.12 1.35 1 0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 Derby 4 Derby 40T Lucene Bank INCREASEFACTOR Dl-Check Jcarder MulticoreSDK Slide 95/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 96. Real-life example Slide 96/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 97. public void testClose() { cm.register(con); // lock cm // lock con for con.onRegister() assertEquals(1, cm.getConCount()); con.close(); // lock con // lock cm for cm.unregister() assertEquals(0, cm.getConCount()); } Slide 97/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 98. ========================== !!! Potential deadlock !!! ========================== ### Cycle in lock graph: ### Lock ConnectionImpl@d70c109 was acquired at: a.ConnectionImpl.onRegister(Sample.java:39) a.ConnectionImpl.close(Sample.java:44) Lock ConnectionManager@2be94b0f was acquired at: a.ConnectionManager.getConCount(Sample.java:24) a.ConnectionManager.register(Sample.java:15) a.ConnectionManager.unregister(Sample.java:20) ### Current lock stack: ### Lock ConnectionImpl@d70c109 was acquired at: a.ConnectionImpl.onRegister(Sample.java:39) a.ConnectionImpl.close(Sample.java:44) ### Current stacktrace: ### a.ConnectionManager.unregister(Sample.java:20) a.ConnectionImpl.close(Sample.java:45) a.FunctionalityTest.testClose(FunctionalityTest.java:22) ... Slide 98/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 99. Evaluation in real projects • Internal projects • IntelliJ IDEA • Kotlin • … Slide 99/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 100. Summary • On-line algorithm for detecting potential deadlocks • JAgent framework for writing Java agents - https://github.com/Devexperts/jagent • Dl-Check tool has been implemented - https://github.com/Devexperts/dlcheck • Further work: - Contracts to describe lock acquisition rules Slide 100/101. Copyright © 2017. Devexperts LLC. All rights reserved.
  • 101. Thank you for attention! Nikita Koval, Devexperts LLC nkoval@devexperts.com twitter.com/nkoval_