`
java-boy
  • 浏览: 244520 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java 内部工作线程介绍

    博客分类:
  • Java
阅读更多

Java程序运行的过程中,不但包括开发者启动的主线程和子线程。还包括很多内部线程。了解这些线程,对了解Java工作原理,及复杂环境下debug会有帮助。

 

首先需要查看Java程序的内部线程,我使用以下两种方法查看Java下的线程:

        1.Jconsole——JDK自带的JMX查看管理工具(GUI)。

        2.Linux下使用kill -3 processId ,发送命令3号信号——QUIT。可以得到该进程的线程堆栈及内存占用情况输出。

        3.jstack <pid>——JDK自带的查看堆栈工具。

 

两种方法对比:

       平常写程序用jconsole,是很好的工具。因为Jconsole可以实时查看内存和堆栈情况,而kill则不能。但对于生产情况kill还是有用武之地的。

       但这回, Kill方法输出的比Jconsole要更全,Jconsole使用的是JMX主要用来是查看进程工作情况,会隐藏一些内部的线程。对写程序没什么影响,但这次我们希望得到全部内部线程用来分析,所以Jconsole是不够用的。

 

需要先说明一下,我的这次测试,是在SUN  HotSpot(TM) Client VM (14.0-b16)——JDK6 情况下的线程结果,由于JVM可以根据协议各自厂商自己实现,可能会有出入。

 

好了,我们先看看跑一个HelloWorld需要开启几个线程:
我的kill -3 processID 后的结果是:

 

Full thread dump Java HotSpot(TM) Client VM (14.0-b16 mixed mode, sharing):

"Low Memory Detector" daemon prio=10 tid=0x08096400 nid=0x6e5 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"CompilerThread0" daemon prio=10 tid=0x08093400 nid=0x6e4 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x08091800 nid=0x6e3 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=10 tid=0x08080400 nid=0x6e2 in Object.wait() [0xb52b2000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x8b7d0b00> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
        - locked <0x8b7d0b00> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=10 tid=0x0807ec00 nid=0x6e1 in Object.wait() [0xb5303000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x8b7d0a08> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:485)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
        - locked <0x8b7d0a08> (a java.lang.ref.Reference$Lock)

"main" prio=10 tid=0x08059000 nid=0x6df waiting on condition [0xb7577000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.test.HelloWorld.main(HelloWorld.java:12)

"VM Thread" prio=10 tid=0x0807d000 nid=0x6e0 runnable

"VM Periodic Task Thread" prio=10 tid=0x080aa000 nid=0x6e6 waiting on condition

JNI global references: 597

Heap
 def new generation   total 960K, used 200K [0x8b7d0000, 0x8b8d0000, 0x8bcb0000)
  eden space 896K,  22% used [0x8b7d0000, 0x8b802068, 0x8b8b0000)
  from space 64K,   0% used [0x8b8b0000, 0x8b8b0000, 0x8b8c0000)
  to   space 64K,   0% used [0x8b8c0000, 0x8b8c0000, 0x8b8d0000)
 tenured generation   total 4096K, used 0K [0x8bcb0000, 0x8c0b0000, 0x8f7d0000)
   the space 4096K,   0% used [0x8bcb0000, 0x8bcb0000, 0x8bcb0200, 0x8c0b0000)
 compacting perm gen  total 12288K, used 18K [0x8f7d0000, 0x903d0000, 0x937d0000)
   the space 12288K,   0% used [0x8f7d0000, 0x8f7d4a30, 0x8f7d4c00, 0x903d0000)
    ro space 8192K,  74% used [0x937d0000, 0x93dc9cc8, 0x93dc9e00, 0x93fd0000)
    rw space 12288K,  59% used [0x93fd0000, 0x946e7540, 0x946e7600, 0x94bd0000)

 

 

为了大家能看清,我特意全拷了上来。需要特意说明的是,我使用的是Sleep方法将进程停住,而不是我通常使用的‘调试’方法。为什么已后进行详细说明。

 

我们能看见HelloWorld实际上创建了如下线程:

"Low Memory Detector"
"CompilerThread0"
"Signal Dispatcher"
"Finalizer"
"Reference Handler"
"main"
"VM Thread"
"VM Periodic Task Thread"

 

由于我手头上的资料也不是很全,简单说明一下都是干什么用的。

"Low Memory Detector" 负责对可使用内存进行检测,如果发现可用内存低,分配新的内存空间。

"CompilerThread0" 用来调用JITing,实时编译装卸class。

"Signal Dispatcher" 负责分发内部事件。

"Finalizer" 负责调用Finalizer方法。

"Reference Handler" 负责处理引用。

"main" 是主线程。

"VM Thread", "VM Periodic Task Thread"从名字上看是虚机内部线程。(这两个在Jconsole下看不见)

 

我们还可以看出实际上只有"main","VM Thread","Low Memory Detector" 在工作。

而"Low Memory Detector" ,"CompilerThread0","Signal Dispatcher","Finalizer","Reference Handler"都是daemo进程。

 

之后我用Jconsole查看了一下,发现多了几个线程:

 

"RMI TCP Connection(4)-127.0.1.1" daemon prio=10 tid=0x08201000 nid=0x2846 runnable [0xac968000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
	- locked <0xad7543a8> (a java.io.BufferedInputStream)
	at java.io.FilterInputStream.read(FilterInputStream.java:66)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:517)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)

"RMI TCP Connection(3)-127.0.1.1" daemon prio=10 tid=0x081edc00 nid=0x2845 runnable [0xac9b9000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
	- locked <0xad7565c0> (a java.io.BufferedInputStream)
	at java.io.FilterInputStream.read(FilterInputStream.java:66)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:517)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)

"RMI TCP Connection(idle)" daemon prio=10 tid=0x081e7000 nid=0x2841 waiting on condition [0xaca0a000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0xad706d50> (a java.util.concurrent.SynchronousQueue$TransferStack)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
	at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
	at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
	at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:945)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
	at java.lang.Thread.run(Thread.java:619)

"JMX server connection timeout 15" daemon prio=10 tid=0x081d6800 nid=0x2839 in Object.wait() [0xaca5b000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0xad7136e8> (a [I)
	at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:150)
	- locked <0xad7136e8> (a [I)
	at java.lang.Thread.run(Thread.java:619)

"RMI Scheduler(0)" daemon prio=10 tid=0x08160c00 nid=0x2838 waiting on condition [0xacaac000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0xad6fdf18> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1963)
	at java.util.concurrent.DelayQueue.take(DelayQueue.java:164)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:583)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:576)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
	at java.lang.Thread.run(Thread.java:619)

"RMI TCP Connection(1)-127.0.1.1" daemon prio=10 tid=0x080fc800 nid=0x2837 in Object.wait() [0xacafd000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0xad740780> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer)
	at com.sun.jmx.remote.internal.ArrayNotificationBuffer.fetchNotifications(ArrayNotificationBuffer.java:417)
	- locked <0xad740780> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer)
	at com.sun.jmx.remote.internal.ArrayNotificationBuffer$ShareBuffer.fetchNotifications(ArrayNotificationBuffer.java:209)
	at com.sun.jmx.remote.internal.ServerNotifForwarder.fetchNotifs(ServerNotifForwarder.java:258)
	at javax.management.remote.rmi.RMIConnectionImpl$2.run(RMIConnectionImpl.java:1227)
	at javax.management.remote.rmi.RMIConnectionImpl$2.run(RMIConnectionImpl.java:1225)
	at javax.management.remote.rmi.RMIConnectionImpl.fetchNotifications(RMIConnectionImpl.java:1231)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
	at sun.rmi.transport.Transport$1.run(Transport.java:159)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)

"RMI TCP Accept-0" daemon prio=10 tid=0x08107400 nid=0x2835 runnable [0xacb4e000]
   java.lang.Thread.State: RUNNABLE
	at java.net.PlainSocketImpl.socketAccept(Native Method)
	at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:390)
	- locked <0xad6fe0e8> (a java.net.SocksSocketImpl)
	at java.net.ServerSocket.implAccept(ServerSocket.java:453)
	at java.net.ServerSocket.accept(ServerSocket.java:421)
	at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:34)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:369)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:341)
	at java.lang.Thread.run(Thread.java:619)

"Attach Listener" daemon prio=10 tid=0x080fb000 nid=0x2834 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE
 

我们从名字可以看出来RMI开头的5个是管理RMI的线程。

JMX的是管理JMX线程。

"Attach Listener"现在不明,但也应该跟Jconsole有关。

以上全部是daemon线程。

 

主要都是用来Jconsole管理该进程时使用的。

 

之后,我又尝试用‘断点’,debug模式,停下程序,发现又多出了三个线程(在jconsole下一样看不见)。

"JDWP Command Reader" daemon prio=10 tid=0x080cb400 nid=0x2827 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"JDWP Event Helper Thread" daemon prio=10 tid=0x080c9400 nid=0x2826 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"JDWP Transport Listener: dt_socket" daemon prio=10 tid=0x080c6c00 nid=0x2823 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

 

 JDWP是Java Debug Wire Protocol的缩写,是Java Debug使用的一种协议。以上三个线程,应该就是用来Debug时,创建的。以上三个全是daemon线程。

 

由于资料缺少,就先写到这里了,已后有资料了在补...........

 

 

 

参考资料:

http://en.allexperts.com/q/Java-1046/Jvm-threads.htm

http://java.sun.com/j2se/1.5.0/docs/guide/jpda/jdwp-spec.html

6
0
分享到:
评论
5 楼 eagledame 2015-08-20  
grefr 写道
关于JVM内部运行线程的介绍,可以看看这个文章,写的相当不错
http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp47



这个资料好
4 楼 kuangxiao163 2014-03-07  
jactive 写道
不错  至少知道了 jconsole ,谢谢

不过我在 fc 下 kill -3 没有任何输出...  应该怎么做呢?


是在java运行的控制台下的输出。
3 楼 GuolinLee 2012-02-07  
长见识了,我第一次用Jconsole来看到有那么隐藏的线程的时候吃了一惊,没想到还有这么多隐藏的线程啊
2 楼 java-boy 2009-11-18  
jstack <pid> 也可以查看进程运行情况。
1 楼 jactive 2009-11-17  
不错  至少知道了 jconsole ,谢谢

不过我在 fc 下 kill -3 没有任何输出...  应该怎么做呢?

相关推荐

    java 查看JVM中所有的线程的活动状况

    java 查看JVM中所有的线程的活动状况 java 查看JVM中所有的线程的活动状况

    java多线程_java多线程下变量共享_

    一个简单记录java多线程下变量共享问题,分析多线程内部运行

    java线程文档

     Java编写程序都运行在在Java虚拟机(JVM)中,在JVM的内部,程序的多任务是通过线程来实现的。每用java命令启动一个java应用程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个...

    java多线程编程_java多线程_

    5.讲解了Timer定时器类, 其内部实现就是使用的多线程技术。 定时器的计划任 务执行是很重要的技术点, 包括在Android开发时都会有深入的使用, 所以会为读者详细 讲解。6.讲解的单例模式虽然很简单, 但如果遇到多...

    java学习多线程处理

    线程:进程内部的一个执行单元,它是程序中一个单一的顺序控制流程。 线程的特点:一个进程可以包含多个线程,而一个线程至少要有一个父进程。 线程可以有自己的堆栈,程序计数器和局部变量。 线程与父进程的其他...

    JAVA多线程实验报告

    利用多线程技术编写applet程序。其中包含一个滚动的字符串,字符串从左向右移动,当所有的字符都从屏幕的右边消失后,字符串重新从左边出现并继续向右移动

    Java线程详解.ppt

    一个进程中可以包含一个或多个线程,一个线程就是程序内部的一条执行线索。 在单线程中,程序代码按调用顺序依次往下执行,不能实现两段程序代码同时交替运行的效果。如果一个程序中要实现两段程序代码同时交替运行...

    java线程内部类练习.rar

    java 线程练习,内部类,接口练习应用。

    Java线程pdf ---培训内部资料

    Java线程 讲到线程的各个方面 培训内部资料

    详细剖析JAVA多线程案例教学

    我们公司是搞移动增值业务的,这是我弄出来的新人培训的内部资料,虽然不是公司编写的,但是公司搜集的。 这个资料对于培训新人来说非常有用,照着资料看一天,敲一天代码基本就会了。

    Java多线程 之 临界区、ThreadLocal.docx

    synchronized关键字不属于方法特征签名的一部分,所以可以在覆盖方法的时候加上去。...如果在一个类内部都是使用synchronized关键字定义了方法f(),g()。那么当使用这个类的实例调用f()时,就不能再调用g()方法。

    java实现线程的异步

    java实现线程的异步...................................

    Java多线程编程 线程同步机制.docx

    线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发...Java平台中的锁包括内部锁和显式锁。内部锁是通过synchronized关键字实现的,显式锁则是通过Lock接口的实现类实现的。

    Java高并发实战_java高并发_高并发_

    第2章介绍了 Java 并行程序开发的基础, 包括 Java 中 Thread 的基本使用方法等第3章介绍了 JDK 内部对并行程序开发的支持, 主要介绍 JUC (Java.util.concurrent) 中些工具的使用方法、 各自特点及它们的内部实现...

    Java多线程与线程安全实践-基于Http协议的断点续传

    基于Http协议的断点续传是Java多线程和线程安全的一个典型应用。下面详细解说一下这个实践的实现过程: 理解Http协议 在实现断点续传之前,我们需要先理解Http协议的基本工作原理。Http协议是一个基于请求-响应模式...

    华为内部java考题

    华为内部的java考题, JAVA考试知识覆盖要点: (1)常用的集合类,如Set、Map、List,以及常用的查找、遍历、排序操作; (2)多线程同步机制; (3)文件读写; (4)XML解析、基本的正则表达式; (5)类的加载和...

    java实现的多线程服务器

    包括一个公共类和一个内部类,能实现为多个客户提供连续的服务

    Java开发企业QQ内部通信系统程序完整练手项目流程实战_优秀案例实例源代码源码.zip

    ( Java Swing+ Derby+多线程+ Socket编程实现)。 近年来,随着中、小型企业的蓬勃发展,各种企业内部通信系统也在飞速发展着。由于企业内部通信系统可以不用链接 Internet,直接在局域网内实现信息通信、工作交流和计划...

    Java实现的企业内部QQ聊天系统

    Java实现的企业内部QQ聊天系统,Socket线程通信,单人,多人在线聊天

    java视频教程(52课)下 异常 IO 线程 类集框架 开发工具之Eclipse 综合练习

    36_Java当中的线程.mp4 37_Java当中的线程(二).mp4 38_Java当中的线程(三).mp4 40_Java当中的数组.mp4 41_类集框架(一).mp4 42_类集框架(二).mp4 44_equals函数的作用.mp4 45_hashCode()与toString().mp4 46_...

Global site tag (gtag.js) - Google Analytics