Skip to content

Instantly share code, notes, and snippets.

@jimbaker
Created September 10, 2013 22:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jimbaker/6516506 to your computer and use it in GitHub Desktop.
Save jimbaker/6516506 to your computer and use it in GitHub Desktop.
An example of using JMX from Jython. In particular, running kill_deadlocked_jvms.py will kill any deadlocked JVM process. To cause a deadlock, simply run deadlock.py with Jython. Although deadlock.py is portable Python, running with Jython does allow for the deadlock detection supported by the JVM. Examples are from my 2012 OSCON talk.
from threading import Thread, Lock
import threading
def cause_deadlock():
lock_one = Lock()
lock_two = Lock()
counter = [0] # Shared resource for both locks
Thread(name="thread #1", target=acquire_locks,
args=(counter, lock_one, lock_two)).start()
Thread(name="thread #2 (reversed)", target=acquire_locks,
args=(counter, lock_two, lock_one)).start()
def acquire_locks(counter, lock1, lock2):
# Will eventually deadlock if locks are acquired in different order
name = threading.currentThread().getName()
thread_count = 0
while True:
with lock1:
with lock2:
counter[0] += 1
thread_count += 1
print "name={}, total count={}, thread count={}".\
format(name, counter[0], thread_count)
if __name__ == '__main__':
cause_deadlock()
import os.path
import signal
from contextlib import closing
from com.sun.tools.attach import VirtualMachine
from java.lang import Class
from java.lang.management import ManagementFactory
from javax.management.remote import JMXServiceURL, JMXConnectorFactory
def get_vm_connectors(exclude_self=True):
my_pid = os.getpid()
for desc in VirtualMachine.list():
vm = VirtualMachine.attach(desc)
pid = int(desc.id())
if exclude_self and pid == my_pid:
continue
connector_addr = vm.agentProperties["com.sun.management.jmxremote.localConnectorAddress"]
if connector_addr is None:
# Need to load a JMX agent into the JVM
system_props = vm.systemProperties
agent = os.path.join(
system_props["java.home"], "lib", "management-agent.jar")
print "Loading management agent={} for pid={}...".format(agent, pid)
vm.loadAgent(agent)
connector_addr = vm.agentProperties["com.sun.management.jmxremote.localConnectorAddress"]
yield pid, connector_addr
def check_and_kill_deadlocked_vm(pid, connector_addr):
url = JMXServiceURL(connector_addr)
print "Checking vm pid={}, url={}".format(pid, url)
with closing(JMXConnectorFactory.connect(url)) as connector:
mbean = connector.MBeanServerConnection
thread_mxbean = ManagementFactory.getPlatformMXBean(
mbean, Class.forName("java.lang.management.ThreadMXBean"))
thread_ids = thread_mxbean.findDeadlockedThreads()
if thread_ids:
print "Deadlock detected, shutting down pid={}, threads={}".\
format(pid, list(thread_ids))
os.kill(pid, signal.SIGINT)
def main():
for pid, connector_addr in get_vm_connectors():
check_and_kill_deadlocked_vm(pid, connector_addr)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment