JAVA自带监控工具的介绍
转:http://www.alidw.com/?p=326
相信部分同学可能还是不太了解或者很少使用,这些监控工具是jdk5.0以上才会有的,有部分是liunx特有的。
了解这些工具再做压力测试和调优方面是特别有用的哦!用好下面介绍的工具完全可以不用jprofile了(它还是收费的),而且速度还快。
下面我就给大家介绍介绍吧。
JPS
用来显示本地的java进程,以及进程号。
我们可以通过它来查看我们到底启动了几个java进程.
jps也可以列出远程服务器的java进程(远程服务需提供jstatd服务,采用rmi协议,默认链接端口1099),通常没人这么干。
JINFO
可以输出并修改运行时的java进程的参数(JVM参数和Java System属性)
jinfo pid 会打印出详细的jvm运行参数和Java System属性。
此命令内容较多。而且输出的也稍慢。不过可以用以下命令来打印出你所关注的参数。
jinfo -flag MaxPermSize pid 该命令查看某个进程的MaxPermSize(MaxPermSize 可以换任意JVM参数 比如PermSize)
[xxxxxxxx ~]$ jinfo -flag MaxPermSize 12191
-XX:MaxPermSize=134217728
-XX:MaxPermSize=134217728
[xxxxxxxx ~]$ jinfo -flag PermSize 12191
-XX:PermSize=134217728
-XX:PermSize=134217728
[admin@dw_web4 ~]$ jinfo -flag LargePageSizeInBytes 12191
-XX:LargePageSizeInBytes=134217728
-XX:LargePageSizeInBytes=134217728
用main jinfo查看更多使用方法介绍
JSTAT(我最喜欢用的) 另外还有一个jvmstat 可视化的,我这里不做介绍 有兴趣http://java.sun.com/performance/jvmstat/ 下载玩玩
监视VM的内存工具,可以用来监视vm内存内的各种堆和非堆的大小及其内存使用量,可以观察到classloader,compiler,gc相关信息。(兴趣高起来了 等下我在提供一个JVM内存管理的图,上一篇博客关于java内存模型主要是介绍写并发程序)
jstat -gcutil:统计gc时,heap情况
[xxxxxxxx ~]$ jstat -gcutil 12191 250 7
S0 S1 E O P YGC YGCT FGC FGCT GCT
100.00 0.00 70.12 2.33 43.55 4 0.243 0 0.000 0.243
100.00 0.00 70.12 2.33 43.55 4 0.243 0 0.000 0.243
100.00 0.00 70.79 2.33 43.56 4 0.243 0 0.000 0.243
100.00 0.00 75.15 2.33 43.79 4 0.243 0 0.000 0.243
100.00 0.00 75.15 2.33 43.79 4 0.243 0 0.000 0.243
100.00 0.00 81.15 2.33 44.51 4 0.243 0 0.000 0.243
100.00 0.00 83.15 2.33 44.63 4 0.243 0 0.000 0.243
S0 S1 E O P YGC YGCT FGC FGCT GCT
100.00 0.00 70.12 2.33 43.55 4 0.243 0 0.000 0.243
100.00 0.00 70.12 2.33 43.55 4 0.243 0 0.000 0.243
100.00 0.00 70.79 2.33 43.56 4 0.243 0 0.000 0.243
100.00 0.00 75.15 2.33 43.79 4 0.243 0 0.000 0.243
100.00 0.00 75.15 2.33 43.79 4 0.243 0 0.000 0.243
100.00 0.00 81.15 2.33 44.51 4 0.243 0 0.000 0.243
100.00 0.00 83.15 2.33 44.63 4 0.243 0 0.000 0.243
间隔250毫秒 打印7行
jstat -gccause 监控内存使用情况 参数 (查看内存溢出相对有用)
[xxxxxxxx ~]$ jstat -gccause 12191 3000 (每隔3秒监控一次)
S0 S1 E O P YGC YGCT FGC FGCT GCT LGCC GCC
100.00 0.00 93.97 2.35 44.71 4 0.259 0 0.000 0.259 unknown GCCause No GC
100.00 0.00 93.97 2.35 44.72 4 0.259 0 0.000 0.259 unknown GCCause No GC
S0 S1 E O P YGC YGCT FGC FGCT GCT LGCC GCC
100.00 0.00 93.97 2.35 44.71 4 0.259 0 0.000 0.259 unknown GCCause No GC
100.00 0.00 93.97 2.35 44.72 4 0.259 0 0.000 0.259 unknown GCCause No GC
….
….
下面copy一份介绍:
S0 Survivor space 0 utilization as a percentage of the space’s current capacity.
S1 Survivor space 1 utilization as a percentage of the space’s current capacity.
E Eden space utilization as a percentage of the space’s current capacity.
O Old space utilization as a percentage of the space’s current capacity.
P Permanent space utilization as a percentage of the space’s current capacity.
YGC Number of young generation GC events.
YGCT Young generation garbage collection time.
FGC Number of full GC events.
FGCT Full garbage collection time.
GCT Total garbage collection time.
LGCC Cause of last Garbage Collection.
GCC Cause of current Garbage Collection.
S1 Survivor space 1 utilization as a percentage of the space’s current capacity.
E Eden space utilization as a percentage of the space’s current capacity.
O Old space utilization as a percentage of the space’s current capacity.
P Permanent space utilization as a percentage of the space’s current capacity.
YGC Number of young generation GC events.
YGCT Young generation garbage collection time.
FGC Number of full GC events.
FGCT Full garbage collection time.
GCT Total garbage collection time.
LGCC Cause of last Garbage Collection.
GCC Cause of current Garbage Collection.
jstat -class pid:显示加载class的数量,及所占空间等信息。
[xxxxxxxx web-deploy]$ jstat -class 12191
Loaded Bytes Unloaded Bytes Time
8209 17577.9 0 0.0 1.68
Loaded Bytes Unloaded Bytes Time
8209 17577.9 0 0.0 1.68
jstat -compiler pid:显示VM实时编译的数量等信息。
[xxxxxxxx web-deploy]$ jstat -compiler 12191
Compiled Failed Invalid Time FailedType FailedMethod
1029 0 0 9.42 0
Compiled Failed Invalid Time FailedType FailedMethod
1029 0 0 9.42 0
jstat -gc pid:可以显示gc的信息,查看gc的次数,及时间。其中最后五项,分别是young gc的次数,young gc的时间,full gc的次数,full gc的时间,gc的总时间。
[xxxxxxxx ~]$ jstat -gc 12191
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
26176.0 26176.0 0.0 26176.0 209792.0 75798.8 1835008.0 72266.8 131072.0 60144.0 5 0.338 0 0.000 0.338
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
26176.0 26176.0 0.0 26176.0 209792.0 75798.8 1835008.0 72266.8 131072.0 60144.0 5 0.338 0 0.000 0.338
jstat
-gccapacity:可以显示,VM内存中三代(包括新生区,老年区,permanent区)对象的使用和占用大小,如:PGCMN显示的是最小
perm的内存使用量,PGCMX显示的是perm的内存最大使用量,PGC是当前新生成的perm内存占用量,PC是但前perm内存占用量。其他的可
以根据这个类推, OC是old内纯的占用量。
[xxxxxxxx ~]$ jstat -gccapacity 12191
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
262144.0 262144.0 262144.0 26176.0 26176.0 209792.0 1835008.0 1835008.0 1835008.0 1835008.0 131072.0 131072.0 131072.0 131072.0 5 0
NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC PGCMN PGCMX PGC PC YGC FGC
262144.0 262144.0 262144.0 26176.0 26176.0 209792.0 1835008.0 1835008.0 1835008.0 1835008.0 131072.0 131072.0 131072.0 131072.0 5 0
jstat -gcnew pid:统计gc时,new新生代的情况
[xxxxxxxx ~]$ jstat -gcnew 12191
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
26176.0 26176.0 0.0 26176.0 1 4 13088.0 209792.0 76512.8 5 0.338
S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
26176.0 26176.0 0.0 26176.0 1 4 13088.0 209792.0 76512.8 5 0.338
jstat -gcnewcapacity pid:new对象的信息及其占用量。
jstat -gcold pid:old对象的信息。
jstat -gcoldcapacity pid:old对象的信息及其占用量。
jstat -gcpermcapacity pid: perm对象的信息及其占用量。
jstat
-printcompilation pid:当前VM执行的信息。除了以上一个参数外,还可以同时加上 两个数字,如:jstat
-printcompilation 3024 250 6是每250毫秒打印一次,一共打印6次,还可以加上-h3每三行显示一下标题。
man jstat查看更详细的吧
JSTACK
可以观察到jvm中当前所有线程的运行情况和线程当前状态
jstack pid 运行看看,内容很多只列出部分
[xxxxxxxx ~]$ jstack 12191
2009-12-24 18:45:19
Full thread dump Java HotSpot(TM) 64-Bit Server VM (11.0-b16 mixed mode):
2009-12-24 18:45:19
Full thread dump Java HotSpot(TM) 64-Bit Server VM (11.0-b16 mixed mode):
“Attach Listener” daemon prio=10 tid=0×0000000044a11c00 nid=0×4430 waiting on condition [0x0000000000000000..0x0000000000000000]
java.lang.Thread.State: RUNNABLE
java.lang.Thread.State: RUNNABLE
“http-0.0.0.0-7001-2″ daemon prio=10 tid=0×000000004546b000 nid=0×2fe5 in Object.wait() [0x00000000423af000..0x00000000423afc90]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
– waiting on <0×00002aaabc8700d8> (a org.apache.tomcat.util.net.MasterSlaveWorkerThread)
at java.lang.Object.wait(Object.java:485)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.await(MasterSlaveWorkerThread.java:81)
– locked <0×00002aaabc8700d8> (a org.apache.tomcat.util.net.MasterSlaveWorkerThread)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:107)
at java.lang.Thread.run(Thread.java:619)
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
– waiting on <0×00002aaabc8700d8> (a org.apache.tomcat.util.net.MasterSlaveWorkerThread)
at java.lang.Object.wait(Object.java:485)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.await(MasterSlaveWorkerThread.java:81)
– locked <0×00002aaabc8700d8> (a org.apache.tomcat.util.net.MasterSlaveWorkerThread)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:107)
at java.lang.Thread.run(Thread.java:619)
“http-0.0.0.0-7001-1″ daemon prio=10 tid=0×0000000045469c00 nid=0×2fe4 in Object.wait() [0x000000004236e000..0x000000004236ec10]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
– waiting on <0×00002aaabcaef5d0> (a org.apache.tomcat.util.net.MasterSlaveWorkerThread)
at java.lang.Object.wait(Object.java:485)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.await(MasterSlaveWorkerThread.java:81)
– locked <0×00002aaabcaef5d0> (a org.apache.tomcat.util.net.MasterSlaveWorkerThread)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:107)
at java.lang.Thread.run(Thread.java:619)
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
– waiting on <0×00002aaabcaef5d0> (a org.apache.tomcat.util.net.MasterSlaveWorkerThread)
at java.lang.Object.wait(Object.java:485)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.await(MasterSlaveWorkerThread.java:81)
– locked <0×00002aaabcaef5d0> (a org.apache.tomcat.util.net.MasterSlaveWorkerThread)
at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:107)
at java.lang.Thread.run(Thread.java:619)
“TP-Monitor” daemon prio=10 tid=0×00002aab406b0000 nid=0×2fe3 in Object.wait() [0x000000004232d000..0x000000004232db90]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at org.apache.tomcat.util.threads.ThreadPool$MonitorRunnable.run(ThreadPool.java:559)
– locked <0×00002aaabcd6ea98> (a org.apache.tomcat.util.threads.ThreadPool$MonitorRunnable)
at java.lang.Thread.run(Thread.java:619)
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at org.apache.tomcat.util.threads.ThreadPool$MonitorRunnable.run(ThreadPool.java:559)
– locked <0×00002aaabcd6ea98> (a org.apache.tomcat.util.threads.ThreadPool$MonitorRunnable)
at java.lang.Thread.run(Thread.java:619)
“TP-Processor4″ daemon prio=10 tid=0×00002aab414f0800 nid=0×2fe2 runnable [0x00000000422ec000..0x00000000422ecb10]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
– locked <0×00002aaabcfedfd8> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:453)
at java.net.ServerSocket.accept(ServerSocket.java:421)
at org.apache.jk.common.ChannelSocket.accept(ChannelSocket.java:306)
at org.apache.jk.common.ChannelSocket.acceptConnections(ChannelSocket.java:660)
at org.apache.jk.common.ChannelSocket$SocketAcceptor.runIt(ChannelSocket.java:870)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:619)
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
– locked <0×00002aaabcfedfd8> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:453)
at java.net.ServerSocket.accept(ServerSocket.java:421)
at org.apache.jk.common.ChannelSocket.accept(ChannelSocket.java:306)
at org.apache.jk.common.ChannelSocket.acceptConnections(ChannelSocket.java:660)
at org.apache.jk.common.ChannelSocket$SocketAcceptor.runIt(ChannelSocket.java:870)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:619)
………………………………………….
……………………………………………
等等。。。
JMAP
打印出某个java进程内存内所有对象的情况(产生的对象以及数量)
jmap -histo pid 打印jvm heap的直方图。其输出信息包括类名,对象数量,对象占用大小。 内容会比较多 不方便查看可以将其保存到文本中去。(jmap -histo pid>histo.log)
该命令检查内存泄漏 是很有用哦。
[xxxxxxxx ~]$ more histo.log
num #instances #bytes class name
———————————————-
1: 251510 39395232 [C
2: 53304 37733944 [I
3: 90608 12763752 <constMethodKlass>
4: 90608 10883664 <methodKlass>
5: 256090 10243600 java.lang.String
6: 8209 9233040 <constantPoolKlass>
7: 74133 9109848 [B
8: 129787 6779512 <symbolKlass>
9: 8209 6552912 <instanceKlassKlass>
10: 111943 6268808 java.util.HashMap$ValueIterator
11: 94562 6051968 java.util.TreeMap$Entry
12: 7083 5493440 <constantPoolCacheKlass>
13: 109800 5270400 org.apache.catalina.LifecycleEvent
14: 28087 5116800 [Ljava.lang.Object;
15: 34532 4681168 [Ljava.util.HashMap$Entry;
16: 27458 4173616 java.lang.reflect.Method
17: 109800 3498960 [Lorg.apache.catalina.Container;
18: 66949 3213552 java.util.HashMap$Entry
19: 109970 2771112 [Lorg.apache.catalina.LifecycleListener;
20: 32831 2101184 java.util.HashMap
21: 34327 1828320 [Ljava.lang.String;
22: 21356 1708480 java.util.TreeMap
23: 8785 1616440 java.lang.Class
———————————————-
1: 251510 39395232 [C
2: 53304 37733944 [I
3: 90608 12763752 <constMethodKlass>
4: 90608 10883664 <methodKlass>
5: 256090 10243600 java.lang.String
6: 8209 9233040 <constantPoolKlass>
7: 74133 9109848 [B
8: 129787 6779512 <symbolKlass>
9: 8209 6552912 <instanceKlassKlass>
10: 111943 6268808 java.util.HashMap$ValueIterator
11: 94562 6051968 java.util.TreeMap$Entry
12: 7083 5493440 <constantPoolCacheKlass>
13: 109800 5270400 org.apache.catalina.LifecycleEvent
14: 28087 5116800 [Ljava.lang.Object;
15: 34532 4681168 [Ljava.util.HashMap$Entry;
16: 27458 4173616 java.lang.reflect.Method
17: 109800 3498960 [Lorg.apache.catalina.Container;
18: 66949 3213552 java.util.HashMap$Entry
19: 109970 2771112 [Lorg.apache.catalina.LifecycleListener;
20: 32831 2101184 java.util.HashMap
21: 34327 1828320 [Ljava.lang.String;
22: 21356 1708480 java.util.TreeMap
23: 8785 1616440 java.lang.Class
..................
..................
..................
jmap -dump:format=b,file=heap.log
12191可以将12191进程的内存heap输出出来到heap.log 文件里。
jmap
-heap pid(该命令我用的比较多) 打印出heap情况,可以观察到New Generation(Eden Space,From
Space,To Space),tenured generation,Perm Generation的内存使用情况。
[xxxxxxxx ~]$ jmap -heap 12191
Attaching to process ID 12191, please wait…
Debugger attached successfully.
Server compiler detected.
JVM version is 11.0-b16
Attaching to process ID 12191, please wait…
Debugger attached successfully.
Server compiler detected.
JVM version is 11.0-b16
using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC
using thread-local object allocation.
Concurrent Mark-Sweep GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 2147483648 (2048.0MB)
NewSize = 268435456 (256.0MB)
MaxNewSize = 268435456 (256.0MB)
OldSize = 805306368 (768.0MB)
NewRatio = 7
SurvivorRatio = 8
PermSize = 134217728 (128.0MB)
MaxPermSize = 134217728 (128.0MB)
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 2147483648 (2048.0MB)
NewSize = 268435456 (256.0MB)
MaxNewSize = 268435456 (256.0MB)
OldSize = 805306368 (768.0MB)
NewRatio = 7
SurvivorRatio = 8
PermSize = 134217728 (128.0MB)
MaxPermSize = 134217728 (128.0MB)
Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 241631232 (230.4375MB)
used = 94646792 (90.26221466064453MB)
free = 146984440 (140.17528533935547MB)
39.16993313182296% used
Eden Space:
capacity = 214827008 (204.875MB)
used = 67842568 (64.69971466064453MB)
free = 146984440 (140.17528533935547MB)
31.580092573835035% used
From Space:
capacity = 26804224 (25.5625MB)
used = 26804224 (25.5625MB)
free = 0 (0.0MB)
100.0% used
To Space:
capacity = 26804224 (25.5625MB)
used = 0 (0.0MB)
free = 26804224 (25.5625MB)
0.0% used
concurrent mark-sweep generation:
capacity = 1879048192 (1792.0MB)
used = 74001208 (70.57305145263672MB)
free = 1805046984 (1721.4269485473633MB)
3.9382283176694597% used
Perm Generation:
capacity = 134217728 (128.0MB)
used = 61586560 (58.7335205078125MB)
free = 72631168 (69.2664794921875MB)
45.885562896728516% used
New Generation (Eden + 1 Survivor Space):
capacity = 241631232 (230.4375MB)
used = 94646792 (90.26221466064453MB)
free = 146984440 (140.17528533935547MB)
39.16993313182296% used
Eden Space:
capacity = 214827008 (204.875MB)
used = 67842568 (64.69971466064453MB)
free = 146984440 (140.17528533935547MB)
31.580092573835035% used
From Space:
capacity = 26804224 (25.5625MB)
used = 26804224 (25.5625MB)
free = 0 (0.0MB)
100.0% used
To Space:
capacity = 26804224 (25.5625MB)
used = 0 (0.0MB)
free = 26804224 (25.5625MB)
0.0% used
concurrent mark-sweep generation:
capacity = 1879048192 (1792.0MB)
used = 74001208 (70.57305145263672MB)
free = 1805046984 (1721.4269485473633MB)
3.9382283176694597% used
Perm Generation:
capacity = 134217728 (128.0MB)
used = 61586560 (58.7335205078125MB)
free = 72631168 (69.2664794921875MB)
45.885562896728516% used
jmap -permstat pid 打印permanent generation heap情况
更多信息查看man jmap
OPTIONS
<no option>
When no option is used jmap prints shared object mappings. For each shared object loaded in the target
VM, start address, the size of the mapping, and the full path of the shared object file are printed. This
is similar to the Solaris pmap utility.
<no option>
When no option is used jmap prints shared object mappings. For each shared object loaded in the target
VM, start address, the size of the mapping, and the full path of the shared object file are printed. This
is similar to the Solaris pmap utility.
-dump:[live,]format=b,file=<filename>
Dumps the Java heap in hprof binary format to filename. The live suboption is optional. If specified,
only the live objects in the heap are dumped. To browse the heap dump, you can use jhat(1) (Java Heap
Analysis Tool) to read the generated file.
Dumps the Java heap in hprof binary format to filename. The live suboption is optional. If specified,
only the live objects in the heap are dumped. To browse the heap dump, you can use jhat(1) (Java Heap
Analysis Tool) to read the generated file.
-finalizerinfo
Prints information on objects awaiting finalization.
Prints information on objects awaiting finalization.
-heap
Prints a heap summary. GC algorithm used, heap configuration and generation wise heap usage are printed.
Prints a heap summary. GC algorithm used, heap configuration and generation wise heap usage are printed.
-histo[:live]
Prints a histogram of the heap. For each Java class, number of objects, memory size in bytes, and fully
qualified class names are printed. VM internal class names are printed with ‘*’ prefix. If the live sub-
option is specified, only live objects are counted.
Prints a histogram of the heap. For each Java class, number of objects, memory size in bytes, and fully
qualified class names are printed. VM internal class names are printed with ‘*’ prefix. If the live sub-
option is specified, only live objects are counted.
-permstat
Prints class loader wise statistics of permanent generation of Java heap. For each class loader, its
name, liveness, address, parent class loader, and the number and size of classes it has loaded are
printed. In addition, the number and size of interned Strings are printed.
Prints class loader wise statistics of permanent generation of Java heap. For each class loader, its
name, liveness, address, parent class loader, and the number and size of classes it has loaded are
printed. In addition, the number and size of interned Strings are printed.
-F Force. Use with jmap -dump or jmap -histo option if the pid does not respond. The live suboption is not
supported in this mode.
supported in this mode.
-h Prints a help message.
-help
Prints a help message.
Prints a help message.
-J<flag>
Passes <flag> to the Java virtual machine on which jmap is run.
Passes <flag> to the Java virtual machine on which jmap is run.
JCONSOLE
一个java GUI监视工具,可以以图表化的形式显示各种数据,并可通过远程连接监视远程的服务器VM。
个人喜欢稍微简单易用jstat来查看。