标签:des http java os io strong for ar art
http://herongyang.com/jtool/jdb.html
http://www.rhcedan.com/2010/06/22/killing-a-java-thread/
用处:上去杀死一个线程,!
"jdb" Command
"jdb": A command line tool that allows you to debug a Java application interactively with in a command line mode. "javac" is distributed as part of the Sun JDK package. It has the following syntax:
jdb [options] main_class_name jdb [options] -attach <address>
where "options" is a list of options, "main_class_name" is a the name of the main class of a Java application, and "address" is the debugging connection address of a running Java application.
As you can see from the syntax, there are two ways of running "jdb":
1. Running "jdb" to launch a Java application and start a debug session on that application.
2. Running "jdb" to connect to a separately launched Java application and start a debug session on that application.
Commonly used options are:
Note that in order to use all debugging commands, the target application must be compiled with "-g" option, which will generate all debugging information, including source file, line number, and local variables, into the class file.
Launching and Debugging Java Applications
To test the debugger, I wrote the following simple Java application, Hello.java:
class Hello { public static void main(String[] a) { System.out.println("Hello world!"); } }
Here is what I did in a command window to run "jdb" to launch and debug Hello.java:
>javac Hello.java >jdb Hello Initializing jdb ... > stop in Hello.main Deferring breakpoint Hello.main. It will be set after the class is loaded. > run run Hello Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable > VM Started: Set deferred breakpoint Hello.main Breakpoint hit: "thread=main", Hello.main(), line=3 bci=0 3 System.out.println("Hello world!"); main[1] next Hello world! > Step completed: "thread=main", Hello.main(), line=4 bci=8 4 } main[1] cont > The application exited
Notice that:
If you want to launch the target application immediately, you can use the "-launch" option:
>jdb -launch Hello Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > VM Started: No frames on the current call stack main[1] cont > Hello world! The application has been disconnected
As we expected, "jdb -launch" command launches the target application immediately, and stops at the beginning of the main() method.
Attaching "jdb" to Running Applications
If you ask "Can I launch the debugger (‘jdb‘) and the target application separately?", the answer is "Yes, you can.". In JDK 1.5, both "jdb" and "java" have been enhanced to use the latest JPDA (Java Platform Debugger Architecture) technology to give you the following options:
Debugger Target Option jdb java 1 Shared memory client Shared memory server 2 Shared memory server Shared memory client 3 Socket client Socket server 4 Socket server Socket client
The shared memory options requires that the debugger and the target application to be on the same machine. Of course, the socket options allow you to run them remotely.
Let‘s try option #1 first. Open a command window on a windows system and run:
>java -agentlib:jdwp=transport=dt_shmem,address=MyHello,server=y, suspend=y Hello Listening for transport dt_shmem at address: MyHello
The target application is launched in "shared memory server" mode. Its execution is suspended. Now open another command window and run:
>jdb -attach MyHello Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > VM Started: No frames on the current call stack main[1] stop in Hello.main Deferring breakpoint Hello.main. It will be set after the class is loaded. main[1] cont > Set deferred breakpoint Hello.main Breakpoint hit: "thread=main", Hello.main(), line=3 bci=0 3 System.out.println("Hello world!"); main[1] list 1 public class Hello { 2 public static void main(String[] a) { 3 => System.out.println("Hello world!"); 4 } 5 } main[1] cont > The application exited
As you can see, the debugger successfully connected to the target application. I used "next" command to let the target application to execute the current statement.
Let‘s try option #3 first. Open a command window on a windows system and run:
>java -agentlib:jdwp=transport=dt_socket,address=localhost:8888,server=y, suspend=y Hello Listening for transport dt_socket at address: 8888
The target application is launched in "socket server" mode. Its execution is suspended. Now open another command window and run:
>jdb -connect com.sun.jdi.SocketAttach:hostname=localhost,port=8888 Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... > VM Started: No frames on the current call stack main[1] stop in Hello.main Deferring breakpoint Hello.main. It will be set after the class is loaded. main[1] cont > Set deferred breakpoint Hello.main Breakpoint hit: "thread=main", Hello.main(), line=3 bci=0 3 System.out.println("Hello world!"); main[1] quite
Cool. I know how to run "jdb" to debug an application running on a remote machine now!
However, the command suggested in the JPDA documentation did not work:
>jdb -attach localhost:8888 java.io.IOException: shmemBase_attach failed: The system cannot find the file specified at com.sun.tools.jdi.SharedMemoryTransportService.attach0(... ...
My guess is that the Windows version of "jdb" assumes "shared memory" as the default transport mode.
Debugging Commands
Ok, I think we did enough about launching the debugger and connecting to the target application. Let‘s now move on to look at some debugging commands.
Here is list of commonly used debugging commands. I got this list by using "help" at debugging prompt.
run [class [args]] -- start execution of an application threads [threadgroup] -- list threads thread <thread id> -- set default thread suspend [thread id(s)] -- suspend threads (default: all) resume [thread id(s)] -- resume threads (default: all) where [<thread id> | all] -- dump a thread‘s stack up [n frames] -- move up a thread‘s stack down [n frames] -- move down a thread‘s stack kill <thread id> <expr> -- kill a thread with the given exception interrupt <thread id> -- interrupt a thread print <expr> -- print value of expression dump <expr> -- print all object information eval <expr> -- evaluate expression (same as print) set <lvalue> = <expr> -- assign new value to a variable locals -- print all local variables classes -- list currently known classes class <class id> -- show details of named class methods <class id> -- list a class‘s methods fields <class id> -- list a class‘s fields threadgroups -- list threadgroups threadgroup <name> -- set current threadgroup stop in <class id>.<method>[(argument_type,...)] -- set a breakpoint in a method stop at <class id>:<line> -- set a breakpoint at a line clear <class id>.<method>[(argument_type,...)] -- clear a breakpoint in a method clear <class id>:<line> -- clear a breakpoint at a line clear -- list breakpoints catch [uncaught|caught|all] <class id>|<class pattern> -- break when specified exception occurs ignore [uncaught|caught|all] <class id>|<class pattern> -- cancel ‘catch‘ watch [access|all] <class id>.<field name> -- watch access/modifications to a field unwatch [access|all] <class id>.<field name> -- discontinue watching trace methods [thread] -- trace method entry and exit untrace methods [thread] -- stop tracing method entry and exit step -- execute current line step up -- execute until the current method returns stepi -- execute current instruction next -- step one line (step OVER calls) cont -- continue execution from breakpoint list [line number|method] -- print source code use (or sourcepath) [source file path] -- display or change the source path classpath -- print classpath info from target VM monitor <command> -- execute command each time the program stops monitor -- list monitors unmonitor <monitor#> -- delete a monitor read <filename> -- read and execute a command file lock <expr> -- print lock info for an object threadlocks [thread id] -- print lock info for a thread disablegc <expr> -- prevent garbage collection of an object enablegc <expr> -- permit garbage collection of an object !! -- repeat last command <n> <command> -- repeat command n times help (or ?) -- list commands version -- print version information exit (or quit) -- exit debugger
Multi-Thread Debugging Exercise
To help me practice debugging commands, I wrote the following simple application, PrimeNumberSeeker.java:
1 /** 2 * PrimeNumberSeeker.java 3 * Copyright (c) 2003 by Dr. Herong Yang, http://www.herongyang.com/ 4 */ 5 public class PrimeNumberSeeker extends Thread { 6 private static final int ceiling = 100; 7 private static final int interval = 1000; 8 private static final int delay = 100; 9 public int count = 0; 10 public int current = 2; 11 public int[] primes = null; 12 public static void main(String[] a) { 13 System.out.println("Period, Current int, # primes"); 14 PrimeNumberSeeker t = new PrimeNumberSeeker(); 15 t.start(); 16 int i = 0; 17 while (true) { 18 i++; 19 System.out.println( i+", "+t.current+", "+t.count); 20 try { 21 sleep(interval); 22 } catch (InterruptedException e) { 23 System.out.println("Monitor interrupted."); 24 } 25 } 26 }
27 public void run() { 28 primes = new int[ceiling]; 29 while (count < ceiling) { 30 current++; 31 int j = 2; 32 boolean isPrime = true; 33 while (j<current/2 && isPrime) { 34 isPrime = current % j > 0; 35 j++; 36 } 37 if (isPrime) { 38 count++; 39 primes[count-1] = current; 40 } 41 try { 42 sleep(delay); 43 } catch (InterruptedException e) { 44 System.out.println("Runner interrupted."); 45 } 46 } 47 } 48 }
Note that:
Here is how I compiled the application and executed without debugging:
>javac -g PrimeNumberSeeker.java >java PrimeNumberSeeker Period, Current int, # primes 1, 2, 0 2, 12, 5 3, 22, 8 4, 32, 11 5, 42, 13 6, 52, 15 7, 62, 18 8, 72, 20 9, 82, 22 10, 92, 24 11, 102, 26 12, 112, 29 13, 122, 30 ... 53, 521, 98 54, 531, 99 55, 541, 100 56, 541, 100 57, 541, 100 ...
The output seems to be fine. But I want to use "jdb" to exam the calculation and to practice the debugging commands. Below I will show my debugging session in multiple parts with my comments.
1. Setting up breakpoints and getting the debugging session going:
>jdb PrimeNumberSeeker Initializing jdb ... > stop in PrimeNumberSeeker.main Deferring breakpoint PrimeNumberSeeker.main. It will be set after the class is loaded. > run run PrimeNumberSeeker Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable > VM Started: Set deferred breakpoint PrimeNumberSeeker.main Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=13 13 System.out.println("Period, Current int, # primes");
main[1] stop in PrimeNumberSeeker.run Set breakpoint PrimeNumberSeeker.run main[1] cont Period, Current int, # primes 1, 2, 0 > Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=28 28 primes = new int[ceiling]; Thread-0[1] threads Group system: (java.lang.ref.Reference$ReferenceHandler)0xe2 Reference Handler (java.lang.ref.Finalizer$FinalizerThread)0xe1 Finalizer (java.lang.Thread)0xe0 Signal Dispatcher Group main: (java.lang.Thread)0x1 main running (PrimeNumberSeeker)0x118 Thread-0 running (at breakpoint)
Ok. What I have done so far:
2. Stepping through the sub thread:
Thread-0[1] where all Signal Dispatcher: Finalizer: [1] java.lang.Object.wait (native method) [2] java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:111) [3] java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:127) [4] java.lang.ref.Finalizer$FinalizerThread.run (Finalizer.java:... Reference Handler: [1] java.lang.Object.wait (native method) [2] java.lang.Object.wait (Object.java:429) [3] java.lang.ref.Reference$ReferenceHandler.run (Reference.java... main: [1] java.lang.Thread.sleep (native method) [2] PrimeNumberSeeker.main (PrimeNumberSeeker.java:21) Thread-0: [1] PrimeNumberSeeker.run (PrimeNumberSeeker.java:28) Thread-0[1] next 2, 2, 0 > Step completed: "thread=Thread-0", PrimeNumberSeeker.run(), line=29 29 while (count < ceiling) { Thread-0[1] where all ... main: [1] java.lang.Thread.sleep (native method) [2] PrimeNumberSeeker.main (PrimeNumberSeeker.java:21) Thread-0: [1] PrimeNumberSeeker.run (PrimeNumberSeeker.java:29) Thread-0[1] next 3, 2, 0 > 30 current++; Thread-0[1] next 4, 3, 0 > 31 int j = 2;
Thread-0[1] next > 5, 3, 0 32 boolean isPrime = true; Thread-0[1] next 6, 3, 0 > 33 while (j<current/2 && isPrime) { Thread-0[1] list 29 while (count < ceiling) { 30 current++; 31 int j = 2; 32 boolean isPrime = true; 33 => while (j<current/2 && isPrime) { 34 isPrime = current % j > 0; 35 j++; 36 } 37 if (isPrime) { 38 count++; Thread-0[1] print current current = 3
What I have done here:
3. Checking local variables:
Thread-0[1] next 7, 3, 0 > 37 if (isPrime) { Thread-0[1] print isPrime isPrime = true Thread-0[1] next 8, 3, 0 > 38 count++; Thread-0[1] next 9, 3, 0 > 39 primes[count-1] = current; Thread-0[1] print count count = 1 Thread-0[1] next > 10, 3, 1 42 sleep(delay); Thread-0[1] list 38 count++; 39 primes[count-1] = current; 40 } 41 try { 42 => sleep(delay); 43 } catch (InterruptedException e) { 44 System.out.println("Runner interrupted."); 45 } 46 } 47 } Thread-0[1] print primes[0] primes[0] = 3
What I have done here:
4. Going back to the main thread:
Thread-0[1] stop at PrimeNumberSeeker:19 Set breakpoint PrimeNumberSeeker:19 Thread-0[1] cont > Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 bci=25 19 System.out.println( i+", "+t.current+", "+t.count); main[1] where all main: [1] PrimeNumberSeeker.main (PrimeNumberSeeker.java:19) Thread-0: [1] java.lang.Thread.sleep (native method) [2] PrimeNumberSeeker.run (PrimeNumberSeeker.java:42) main[1] print i i = 11 main[1] print t.current t.current = 3 main[1] print t.count t.count = 1
What I have done here:
5. Switching threads:
main[1] cont > Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 bci=25 19 System.out.println( i+", "+t.current+", "+t.count); main[1] print t.current t.current = 14 main[1] print t.count t.count = 6 main[1] where all ... main: [1] PrimeNumberSeeker.main (PrimeNumberSeeker.java:19) Thread-0: [1] java.lang.Thread.sleep (native method) [2] PrimeNumberSeeker.run (PrimeNumberSeeker.java:42) main[1] threads ... Group main: (java.lang.Thread)0x1 main running (PrimeNumberSeeker)0x118 Thread-0 running (at breakpoint) main[1] thread 280 Thread-0[1] list Current method is native Thread-0[1] step out 11, 22, 8 > Step completed: "thread=Thread-0", PrimeNumberSeeker.run(), line=45 45 } Thread-0[1] list 41 try { 42 sleep(delay); 43 } catch (InterruptedException e) { 44 System.out.println("Runner interrupted."); 45 => } 46 } 47 } 48 } Thread-0[1] print count count = 8
What I have done here:
6. Running one thread only:
Thread-0[1] stop at PrimeNumberSeeker:39 Set breakpoint PrimeNumberSeeker:39 Thread-0[1] cont > Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current; Thread-0[1] cont > Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 19 System.out.println( i+", "+t.current+", "+t.count); main[1] cont > 12, 23, 9 Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current; Thread-0[1] cont > Breakpoint hit: "thread=main", PrimeNumberSeeker.main(), line=19 19 System.out.println( i+", "+t.current+", "+t.count); main[1] suspend 1 main[1] cont > Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current; Thread-0[1] cont > Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current; Thread-0[1] cont > Breakpoint hit: "thread=Thread-0", PrimeNumberSeeker.run(), line=39 39 primes[count-1] = current; Thread-0[1] print current current = 41 Thread-0[1] print count count = 13
What I have done here:
I think I have done enough debugging practice and want to stop here now. However, my program does have a calculation error. I want to leave it to you to find out.
Conclusions
This was amazingly impossible to find the answer to when I was looking for it.
The setup — running JVM, some thread doing something stupid like taking 100% CPU usage. For the purposes of my example, I will explain that I was using Jetty to serve a homegrown web application. With an Apache front-end, requests were being passed to Jetty over the AJP13 protocol using mod_jk.
Basically, the result of months of research turned out to be that a misconfigured client browser was passing a “Content-Length” value in the header of the request that was greater than the amount of data that was actually being supplied by the request. That’s stupid, right? What’s stupider is that in this situation, mod_jk winds up passing this crap along to Jetty, and with AJP13, Jetty sits there waiting for more data to come from the connector. But, there is no more data. So, away it would spin… until the service could be completely restarted, causing a service interruption for end-users. This was not acceptable, so before I was able to find what was actually causing the problem, I spent a long time finding a suitable work-around to the bug. The logical answer seemed to be “killing a java thread” — and I honestly thought that somebody else out there in the world had somehow found a way to kill a java thread. Apparently nobody in the mass of all google search results has ever found a way to kill a java thread that is attached to a running JVM, without destroying the entire JVM… at least not that I found.
So, for all of you guys out there that want/need to do the same thing — here’s your solution:
1) Ensure that your java program is started with the following parameters:
-Dcom.sun.management.jmxremote.port=50199 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Xrunjdwp:transport=dt_socket,address=50100,server=y,suspend=n
This will allow us to attach the java debugger to the running process, after we identify which Thread is causing the problem. Also, make sure that you have your iptables setup appropriately so as to only allow connections on 50100 and 50199 from the hosts/workstations that you manage.
2) Identify the offending thread:
In order to identify the offending thread, I used the Java VisualVM
utility that is shipped with the JDK distribution. You can also use
JConsole, but VisualVM allows you to add in JConsole plugins, and the
look/feel is so much better than JConsole, so I use VisualVM. We’ll need
the JTop JConsole plugin, which you can find in /demo/management/JTop.jar. I trust you’ll be able to figure out how to get the plugin working…
The thread that is eating your CPU will be at the top of the list. For
the purposes of this example, the image below is an infant thread, so
the CPU(sec) column reflects only a few seconds worth of actual usage —
yours may/probably will be much higher.
3) Kill the thread.
In this example, the ThreadName is “btpool0-0″. Fire up the java
debugger (also shipped with the JDK distribution), and attach to the
running JVM…
[root@host ~]# jdb -attach 50100
Get a list of the running threads — this will also give us the thread id as the JVM sees it:
Set uncaught java.lang.Throwable Set deferred uncaught java.lang.Throwable Initializing jdb ... < threads Group system: (java.lang.ref.Reference$ReferenceHandler)0x25c1 Reference Handler cond. waiting (java.lang.ref.Finalizer$FinalizerThread)0x25c2 Finalizer cond. waiting (java.lang.Thread)0x25c3 Signal Dispatcher running (java.lang.Thread)0x25c4 RMI TCP Accept-0 running (java.lang.Thread)0x25c5 RMI TCP Accept-50199 running (java.lang.Thread)0x25c6 RMI TCP Accept-0 running (java.lang.Thread)0x25c7 RMI Scheduler(0) cond. waiting Group main: (java.util.TimerThread)0x25ca Timer-0 cond. waiting (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25cb btpool0-0 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25cc btpool0-1 - Acceptor0 SelectChannelConnector@0.0.0.0:8080 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25cd btpool0-2 - Acceptor1 SelectChannelConnector@0.0.0.0:8080 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25ce btpool0-3 - Acceptor0 Ajp13SocketConnector@0.0.0.0:8009 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25cf btpool0-4 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25d0 btpool0-5 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25d1 btpool0-6 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25d2 btpool0-7 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25d3 btpool0-8 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25d4 btpool0-9 running (java.util.TimerThread)0x25d5 Timer-1 cond. waiting (java.lang.Thread)0x25d6 PoolScavenger0 cond. waiting (oracle.jdbc.pool.OracleImplicitConnectionCacheThread)0x25d8 Thread-15 sleeping (java.util.TimerThread)0x25d9 Timer-2 cond. waiting (java.lang.Thread)0x25db Thread-18 cond. waiting (java.util.TimerThread)0x25dc Timer-3 cond. waiting (java.util.TimerThread)0x25dd Timer-4 cond. waiting (java.lang.Thread)0x25de Northgate Server running (java.util.TimerThread)0x25df Timer-5 cond. waiting (java.util.TimerThread)0x25e0 Timer-6 cond. waiting (java.util.TimerThread)0x25e1 Timer-7 cond. waiting (java.util.TimerThread)0x25e2 Timer-8 cond. waiting (java.util.TimerThread)0x25e3 Timer-9 cond. waiting (java.lang.Thread)0x25e4 pool-1-thread-1 cond. waiting (java.util.TimerThread)0x25e5 Timer-10 cond. waiting (java.lang.Thread)0x25e6 DestroyJavaVM running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25e7 btpool0-10 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25e8 btpool0-11 running (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25e9 btpool0-12 running (oracle.jdbc.pool.OracleImplicitConnectionCacheThread)0x25ea Thread-756 sleeping (org.mortbay.thread.BoundedThreadPool$PoolThread)0x25eb btpool0-13 cond. waiting Group RMI Runtime: (java.lang.Thread)0x25ed JMX server connection timeout 51 cond. waiting (java.lang.Thread)0x25ee RMI TCP Connection(2687)-127.0.0.1 running >
The thread id that we’re going to kill is “0x25cb”. The first step of killing the thread is to jump into it, and suspend it…
> thread 0x25cb btpool0-0[1] suspend 0x25cb
Now, here’s the real trick, and the primary component of killing the thread that I was unable to find in all of the search that I had done… Step to the next frame.
btpool0-0[1] step > Step completed: <... snip ...>
This puts you in a position to inject a general exception into the running code (should probably be something that is uncaught), thereby exiting the running thread, and cleaning up objects gracefully within the JVM.
btpool0-0[1] kill 0x25cb new java.lang.Exception() killing thread: btpool0-0 btpool0-0[1] instance of com.site.package.name(name=‘btpool0-0‘, id=9675) killed btpool0-0[1]
Exit the java debugger, and you’re done!
-dan
标签:des http java os io strong for ar art
原文地址:http://www.cnblogs.com/jvava/p/3935563.html