`
gaozzsoft
  • 浏览: 414758 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

面霸宝典Notes(二)

 
阅读更多

java6大设计原则:

一 : 类单一职责原则:

        一个类只有一个引起这个类变化的原因。即一个类只完成一个功能,如果做不到一个类只完成一个功能,最少要保证一个方法只完成一个功能。

二:依赖倒置原则:

       高层组件应该依赖抽象而不依赖具体,即面向接口编程,一般依赖的成员变量或者参数都应该是抽象的不应该是具体的。

三:里氏代换原则:

     凡是父类出现的地方都可以用子类代替并且原功能没有发生变化,子类不应该覆盖父类的非抽象方法。

四:迪米特法则:

     一个类要尽量的封装自己,一个类只与自己的朋友类打交道一般朋友类是成员变量或者参数,非朋友类一般都是局部变量

五:接口隔离原则:

    一个接口完成的功能尽可能的单一,不要让一个接口承担过多的责任。

六:开闭原则:

      对扩展开放,对修改闭合

 

1) Open-Close Principle(OCP),开-闭原则,讲的是设计要对扩展有好的支持,而对修改要严格限制。这是最重要也是最为抽象的原则,基本上我们所说的Reusable Software既是基于此原则而开发的。其他的原则也是对它的实现提供了路径。

2) Liskov Substituition Principle(LSP),里氏代换原则,很严格的原则,规则是“子类必须能够替换基类,否则不应当设计为其子类。”也就是说,子类只能去扩展基类,而不是隐藏或覆盖基类.
3) Dependence Inversion Principle(DIP),依赖倒换原则,“设计要依赖于抽象而不是具体化”。换句话说就是设计的时候我们要用抽象来思考,而不是一上来就开始划分我需要哪些哪些类,因为这些是具体。这样做有什么好处呢?人的思维本身实际上就是很抽象的,我们分析问题的时候不是一下子就考虑到细节,而是很抽象的将整个问题都构思出来,所以面向抽象设计是符合人的思维的。另外这个原则会很好的支持OCP,面向抽象的设计使我们能够不必太多依赖于实现,这样扩展就成为了可能,这个原则也是另一篇文章《Design by Contract》的基石。

4) Interface Segregation Principle(ISP),“将大的接口打散成多个小接口”,这样做的好处很明显,我不知道有没有必要再继续描述了,为了节省篇幅,实际上我对这些原则只是做了一个小总结,如果有需要更深入了解的话推荐看《Java与模式》,MS MVP的一本巨作!^_^

5) Composition/Aggregation Reuse Principle(CARP),设计者首先应当考虑复合/聚合,而不是继承(因为它很直观,第一印象就是“哦,这个就是OO啊”)。这个就是所谓的“Favor Composition over Inheritance”,在实践中复合/聚合会带来比继承更大的利益,所以要优先考虑。

6) Law of Demeter or Least Knowlegde Principle(LoD or LKP),迪米特法则最少知识原则,这个原则首次在Demeter系统中得到正式运用,所以定义为迪米特法则。它讲的是“一个对象应当尽可能少的去了解其他对象”。也就是又一个关于如何松耦合(Loosely-Coupled)的法则。

单一职责原则

 

一个类永远只有一个职责。

 

一套软件就像是一个团队,每个类就是团队中的一个成员。团队如果想稳定的发展。这些类就要各司其职,分工明确。如果类之间的功能出现了混淆,那么软件的整体结构就会非常的混乱。就像管理学中的一句话,如果一个职责由每个员工负责,那么这个职责就没有员工在负责。 这个原则的概念非常简单,也是非常基础的。很多人尽管没有学习过面向对象的思想,但是经常写代码之后也会不自觉的遵守这个原则。

 

Ps:在遵循单一职责原则的时候,常常会遇到职责扩散的问题。什么是职责扩散呢?这里简单说下,在日志生活中,我们在分类职责时,发现很多平常不受重视的职责,但是这些职责又不能忽视。于是就依次累加,最后分起类来会无穷无尽(有兴趣的读者可以参考下长尾定理)。为了解决这种问题,我们就需要有一些类,他的职责比较综合(类似于“其它”)。类似于一个帮助类。但是这个类又不能太复杂了,否则我们就应该考虑怎么把这个类分离开来。究竟这个类的复杂程度到了什么时候情况下,我们就应该拆分呢?这个需要程序员根据软件自身的复杂情况来判断,没有一个统一的标准。

 

里氏替换原则

 

“Inheritance should ensure that any property proved about supertype objects also holds for subtype objects.”

——“继承必须确保超类所拥有的性质在子类中仍然成立“

 

 这个原则主要是为了体现面向对象的“继承”特征来提出的。 它的主旨就是,能够使用基类的地方,必然也能够透明的使用其子类,并且保证不会出错。为了保证这种透明的无差别的使用,子类在使用时不应该随意的重写父类已经定义好的非抽象的方法。因为这些非抽象方法,类似于某种职能或契约,当父类保持这种约定时,子类也应该遵循并保证该特性,而非修改该特性。 我们在写代码的时候,如果一个参数设定的是基类(或接口、抽象类),那么我们传送子类进去,一样可以正常使用。因为基类相对于父类,只是一个更丰富,更具体,更详细的表现形式。而不应该出现,传入父类运行某种方法没有问题,可是传入子类运行时就报错了。这在日常生活中也可以理解,汽车作为父类,他下面有卡车、轿车。轿车下边又有两厢,三厢等不同的继承。但是无论是哪种汽车(父类)的职能,对于他的子类(卡车或轿车)都应该具有相同的职能,而不是相反的职能。以至于子类的子类(本例中是两厢轿车)也应该拥有汽车一致的功能。

 

我们在写代码中,很容易出现复写了父类的方法后,父类的方法发生了改动,而未考虑到子类的方法也需要作出相应的改动,导致代码出现错误。 通俗一点,可以理解为子类是遗传自父类的。他在各种职能上也应该一脉相承自父类。而不应该随意改变。  

 

 

 

Ps:为什么要叫里氏替换原则呢?这是因为最早提出这个理论的人姓里Liskov。这是计算机中少有的以姓氏命名的东西。

 

最少知道原则

 

Only talk to your immediate friends。永远只和你的朋友交流。

 

我们在学习编程的初期,都会有人告诉我们要遵循“高内聚,低耦合”。而OO中也将“封装”作为对象的基本特征之一。最少知道原则其实体现的就是“高内聚,低耦合”这句话。

 

(1)低耦合:一个类对于自己依赖的类,知道的越少越好。不要让一个类依赖过多的类。否则这个类很容受外界的影响,并且因为这种影响要改变自身的代码(自身要适应)。

 

(2)高内聚:将实现逻辑都封装在类的内部,对public方法以外的信

息,不轻易暴露给外界。

 

这是由于public对外后,相当于是一种契约,一种许诺。你要再后边的实现中,不断的去兼容这种public,以防止调用它的代码不会报错。 上面这样说,可能有点抽象,这里举个例子。在很多人对另一方的要求,都有一条,社会关系不要复杂。为什么会这样呢?因为一个人如果他和外界的关系越复杂,他就越不稳定,不怕人找事,就怕事找人。或许他的本性是好的,但是周边的龙鱼混杂,三天两头的总会有事。避免这种问题的最好办法,就是一开始就做一个安静的美男子。


接口隔离原则

 

一个类对于另外一个类的依赖应该建立在最小的接口上。

 

一个接口定义的过于臃肿,则代表他的每一个实现类都要考虑所有的实现逻辑。如果一个类实现了某个接口,也就是说这个类承载了这个接口所有的功能,维护这些功能成为了自己的职责。这就无形中增加了一个类的负担。

这里有两点需要说明一下:

 

(1)接口定义的小,但是要有限度。对接口细化可以增加灵活性,但是过度细化则会使设计复杂化。同时接口的使用率不高,提高了代码的维护成本。这种极端的体现就是每个接口只含有一个方法,这显然是不合适的。

(2)接口隔离原则和单一原则的区别

 

共同点:都是尽可能的缩小涉及的范围。

不同点:单一原则主要是指封装性。他针对的是一个类、一个方法,是从对象的角度考虑的。而接口隔离原则是指类之间的耦合应该保持的一个度。他针对的是类(对象)和类(对象)之间的关系。如果说单一原则指的是思想单纯,那么接口隔离指的就是社会关系简单啦。

 

依赖置换原则

 

这个原则的名字比较唬人,我们先看看他的内容究竟是什么。在设计模式中对该原则有两句经典的描述:

(1)高层模块不应该依赖底层模块。两者都应该依赖抽象。

(2)抽象不应该依赖细节,细节应该依赖抽象。

 

这两句话的含义是:高层模块不应该依赖底层模块。两者应该通过抽象的东西进行关系链接(抽象的东西是指接口或者抽象类)。其次抽象类或者一个接口不应该依赖某个实现类。而这些实现类反而应该依赖于这个抽象类的设定。

 

通俗一点的说法就是,模块之间不应该直接产生调用关系(这是旧有的调用关系),两者应该通过面向接口(或者理解为面向设定的契约)进行编程。而这些契约和接口更不应该以来自底层模块而设定。这些底层模块反而应该遵守这些契约。因为契约(抽象类、接口)相对于哪些实现代码,更不会改变,也就是更稳定。所以依赖置换原则又叫作面向接口编程或面向契约编程。本意就是调整原来的依赖关系,重行进行了设定。

 

开闭原则

 

开闭原则是指:一个软件、一套系统在开发完成后,当有增加或修改需求时,应该对拓展代码打开,对修改原有代码关闭。

 

类一旦确定,就不应该再对其功能发生修改。这是面向对象设计中,最重要最核心的原则。方案发布后,我们最担心的是什么?就是需求的变化,而需求一旦有变化,就要修改代码。大部分的bug往往就是这时候引入的。因为修改代码时,我们往往将重点放在,如何解决当前bug上,反而没有注意因为这个修改,对原有设计的影响。

 

这条原则没有具体的指导要求,是前边五条原则的根本。

 

 

ps:这六个面向对象的原则,并不是是和否的问题,也不是遵守和不遵守的问题。而是遵守的多和遵守的少的问题。我在文中也多次强调,我们在设计时,应该注意把握一个度。诚然尽可能的遵守这些原则,会使代码维护起来更容易。但是维护粒度过细,所需要的设计和开发成本成倍增加,这显然是舍本逐末的。如图,面向对象开发原则可以从以下这个坐标图展示,不论是哪个维度,他的值都不应该过满,甚至溢出,当然也不能很低,保持一个适当的度即可。

 

 

 一、概述

程序运行中经常会遇到各种问题,定位问题时通常需要综合各种信息,如系统日志、堆dump文件、线程dump文件、GC日志等。通过虚拟机监控和诊断工具可以帮忙我们快速获取、分析需要的数据,进而提高问题解决速度。 本文将介绍虚拟机常用监控和问题诊断命令工具的使用方法,主要包含以下工具:
jps 显示系统中所有Hotspot虚拟机进程
jstat 收集Hotspot虚拟机各方面运行数据
jstack 显示虚拟机的线程栈信息
jinfo 显示虚拟机的配置信息
jmap 用于生成虚拟机的内存快照信息

以上工具的官方文档地址: http://docs.oracle.com/javase/1.5.0/docs/tooldocs/
图形化工具如jconsole,jvisualvm将另文介绍。

二、工具介绍 
1. jps 
JVM Process Status Tool,该命令用于列出正在运行的虚拟机进程,显示main类的名称和虚拟机进程id。该命令受当前用户的访问权限影响,比如linux下非root用户只列出当前用户启动的虚拟机进程。

命令格式:
jps [options] [hostid]

执行示例:

1
2
3
4
$ jps -l 
3733 sun.tools.jps.Jps 
3700 com.leanworld.JVMTools 
com.leanworld.JVMTools即为上面的示例代码执行类。

常用参数:
-l 输出主类全名
-v 输出虚拟机进程启动的jvm参数
-m 输出启动时传递给main函数的参数

2. jstat 
JVM Statistics Monitoring Tool,用于监控各种运行状态信息的命令。在只有文本控制台的环境中(如企业中的生产环境),该工具非常有用。 可以用来显示系统中类装载、垃圾回收、运行期编译状况等运行数据。

命令格式:
jstat [ generalOption | outputOptions vmid [interval[s|ms] [count]] ]
vmid表示虚拟机唯一标识符,如果是本地虚拟机进程,与LVMID一致,通常为本地虚拟机进程号。 interval表示查询间隔时间,count表示查询次数。如果省略interval和count参数,表示查询一次。

执行示例:

1
2
3
4
5
6
$ jstat -gcutil 3700 500 4 
  S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT   
50.00   0.00  60.78   0.50  12.76    214    0.049     0    0.000    0.049 
  0.00  25.00  20.27   0.50  12.76    215    0.049     0    0.000    0.049 
  0.00  25.00  70.91   0.50  12.76    215    0.049     0    0.000    0.049 
50.00   0.00  20.27   0.50  12.76    216    0.049     0    0.000    0.049

S0和S1表示Survivor0和Survivor1,E表示新生代Eden,O表示老年代Old,P表示持久代Permanent,以上各参数值表示已使用空间占比。 YGC表示young gc次数,YGCT表示young gc总耗时。FGC表示Full gc次数,FGCT表示full gc总耗时。GCT表示所有gc总耗时时间。

常用参数:
class 类装载相关信息.
compiler JIT编译器编译过的方法、耗时等.
gc java堆信息和垃圾回收状况.
gccapacity 关注java堆各个区的最大和最小空间.
gccause 类似gcutil,额外输出导致上一次gc的原因.
gcnew 新生代gc状况.
gcnewcapacity 关注新生代gc使用的最大和最小空间.
gcold 老年代gc状况.
gcoldcapacity 关注老年代gc使用的最大和最小空间.
gcpermcapacity 关注持久代gc使用的最大和最小空间.
gcutil 关注已使用空间占总空间比例.
printcompilation 输出已经被JIT编译的方法.

3. jstack 
Stack Trace for Java,用于生成虚拟机当前的线程快照信息,包含每一条线程的堆栈信息。该命令通常用于定位线程停顿原因,当出现线程停顿时,可通过stack查看每个线程的堆栈信息,进而分析停顿原因。
命令格式:
jstack [ option ] pid

执行示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
$ jstack 3700 
2012-01-30 16:36:05 
Full thread dump Java HotSpot(TM) Server VM (17.0-b16 mixed mode): 
 
"Attach Listener" daemon prio=10 tid=0xaca16c00 nid=0x1384 waiting on condition [0x00000000] 
   java.lang.Thread.State: RUNNABLE 
 
"Low Memory Detector" daemon prio=10 tid=0xaca00c00 nid=0x1366 runnable [0x00000000] 
   java.lang.Thread.State: RUNNABLE 
 
"CompilerThread1" daemon prio=10 tid=0x08e58800 nid=0x1365 waiting on condition [0x00000000] 
   java.lang.Thread.State: RUNNABLE 
 
"CompilerThread0" daemon prio=10 tid=0x08e56800 nid=0x1364 waiting on condition [0x00000000] 
   java.lang.Thread.State: RUNNABLE 
 
"Signal Dispatcher" daemon prio=10 tid=0x08e54c00 nid=0x1363 runnable [0x00000000] 
   java.lang.Thread.State: RUNNABLE 
 
"Finalizer" daemon prio=10 tid=0x08e39000 nid=0x1361 in Object.wait() [0xac943000] 
   java.lang.Thread.State: WAITING (on object monitor) 
at java.lang.Object.wait(Native Method) 
- waiting on <0xb10e0230> (a java.lang.ref.ReferenceQueue$Lock) 
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118) 
- locked <0xb10e0230> (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=0x08e34400 nid=0x1360 in Object.wait() [0xacb94000] 
   java.lang.Thread.State: WAITING (on object monitor) 
at java.lang.Object.wait(Native Method) 
- waiting on <0xb10e30d0> (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 <0xb10e30d0> (a java.lang.ref.Reference$Lock) 
 
"main" prio=10 tid=0x08d7bc00 nid=0x135a waiting on condition [0xb6a8a000] 
   java.lang.Thread.State: TIMED_WAITING (sleeping) 
at java.lang.Thread.sleep(Native Method) 
at com.leanworld.JVMTools.createList(JVMTools.java:23) 
at com.leanworld.JVMTools.main(JVMTools.java:29) 
 
"VM Thread" prio=10 tid=0x08e31c00 nid=0x135f runnable 
 
"GC task thread#0 (ParallelGC)" prio=10 tid=0x08d83800 nid=0x135b runnable 
 
"GC task thread#1 (ParallelGC)" prio=10 tid=0x08d85000 nid=0x135c runnable 
 
"GC task thread#2 (ParallelGC)" prio=10 tid=0x08d86400 nid=0x135d runnable 
 
"GC task thread#3 (ParallelGC)" prio=10 tid=0x08d87c00 nid=0x135e runnable 
 
"VM Periodic Task Thread" prio=10 tid=0xaca02c00 nid=0x1367 waiting on condition 
 
JNI global references: 854 
通过输出信息可以看出当前main线程处于TIMED_WAITING状态,因为执行到示例代码中Thread.sleep(100);这行的缘故。

常用参数:
-l 除堆栈外,显示锁的附加信息
-F 当请求不被响应时,强制输出线程堆栈
-m 混合模式,打印java和本地C++调用的堆栈信息

4. jinfo
Configuration Info for Java,用于查看和修改虚拟机的各项参数信息。
命令格式:
jinfo [ option ] pid

执行示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$jinfo 3700 
Attaching to process ID 5081, please wait... 
Debugger attached successfully. 
Server compiler detected. 
JVM version is 17.0-b16 
Java System Properties: 
 
java.runtime.name = Java(TM) SE Runtime Environment 
sun.boot.library.path = /home/learnworld/software/jdk1.6.0_21/jre/lib/i386 
java.vm.version = 17.0-b16 
java.vm.vendor = Sun Microsystems Inc. 
java.vendor.url = http://java.sun.com/ 
path.separator = : 
java.vm.name = Java HotSpot(TM) Server VM 
file.encoding.pkg = sun.io 
sun.java.launcher = SUN_STANDARD 
user.country = CN 
sun.os.patch.level = unknown 
java.vm.specification.name = Java Virtual Machine Specification 
user.dir = /home/learnworld/workspace/concurrency 
java.runtime.version = 1.6.0_21-b06 
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment 
java.endorsed.dirs = /home/learnworld/software/jdk1.6.0_21/jre/lib/endorsed 
os.arch = i386 
java.io.tmpdir = /tmp 
line.separator = 
 
... 
 
VM Flags: 
-Xmn10m -Xms40m -Xmx40m -Dfile.encoding=GBK -Xbootclasspath:/home/learnworld/software/jdk1.6.0_21/lib/tools.jar:/home/learnworld/software/jdk1.6.0_21/lib/sa-jdi.jar:/home/learnworld/software/jdk1.6.0_21/lib/jconsole.jar:/home/learnworld/software/jdk1.6.0_21/lib/htmlconverter.jar:/home/learnworld/software/jdk1.6.0_21/lib/dt.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/rt.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/resources.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/plugin.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/management-agent.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/jsse.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/jce.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/javaws.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/deploy.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/charsets.jar:/home/learnworld/software/jdk1.6.0_21/jre/lib/alt-rt.jar 
可以看出,该命令可以方便我们查找需要的虚拟机信息,包含System.getProperties()信息。

常用参数:
-flag name 打印虚拟机该参数对应的值.
-flag [+\-]name 使该参数生效或失效.
-flag name=value 修改相应参数的值.
-flags 打印传给jvm的参数值.
-sysprops 打印System.getProperties()信息.

5. jmap
Memory Map for Java,可以产生堆dump文件,查询堆和持久代的详细信息等。
命令格式:
jmap [ option ] pid

执行示例:

1
2
3
$ jmap -dump:format=b,file=dump.tmp 3700 
Dumping heap to /home/learnworld/dump.tmp ... 
Heap dump file created

上面这个命令生成了dump.tmp这个dump文件。生成的dump文件可以使用Eclipse Memory Analyzer/jhat等工具进行分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ jmap -permstat 3700 
Attaching to process ID 3700, please wait... 
Debugger attached successfully. 
Server compiler detected. 
JVM version is 17.0-b16 
1355 intern Strings occupying 183024 bytes. 
finding class loader instances ..Finding object size using Printezis bits and skipping over... 
done. 
computing per loader stat ..done. 
please wait.. computing liveness....done. 
class_loader	classes	bytes	parent_loader	alive?	type 
 
<bootstrap>	320	1437208	  null  live	<internal> 
0xb1170250	10	77120	0xb11706b8	live	sun/misc/Launcher$AppClassLoader@0xad34eb70 
0xb11706b8	0	0	  null  live	sun/misc/Launcher$ExtClassLoader@0xad303d40 
 
total = 3	330	1514328	    N/A    alive=3, dead=0	    N/A 
 
常用参数: 
-dump	生成堆dump文件,格式为: -dump:[live,]format=b,file=<filename>
-heap	显示java堆的详细信息,包括垃圾回收期、堆配置和分代信息等
-histo	显示堆中对象的统计信息,包括类名称,对应的实例数量和总容量
-permstat	统计持久代中各ClassLoader的统计信息。

三、遇到的问题
我的操作系统为ubuntu10.10,初次使用jinfo和jmap时出现以下错误:
引用

1
2
Attaching to process ID 3538, please wait... 
Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process

解决方法:
1. echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
该方法在下次重启前有效。

2. 永久有效方法
sudo vi /etc/sysctl.d/10-ptrace.conf
编辑下面这行:
kernel.yama.ptrace_scope = 1
修改为:
kernel.yama.ptrace_scope = 0
重启系统,使修改生效。
该bug详细信息请参考官方文档: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=705本文固定链接: http://www.chepoo.com/java-jvm-command-tools.html | IT技术精华网

 

Java线程状态

线程的五种状态

* 新建:new(时间很短)

* 运行:runnable

* 等待:waitting(无限期等待),timed waitting(限期等待)

* 阻塞:blocked

* 结束:terminated(时间很短)

Jvm监控工具

一、jstack

介绍:

jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。
如果是在64位机器上,需要指定选项"-J-d64",Windows的jstack使用方式只支持以下的这种方式:jstack [-l] pid
如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题。
另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息, 如果现在运行的java程序呈现hung的状态,jstack是非常有用的。

使用:

1、查看运行程序的进程号

2、jstack dump当前线程状态

3、根据当前抓取到的信息进行进一步的分析

二、jvisualvm

jdk自带有个jvisualvm工具、该工具是用来监控java运行程序的cpu、内存、线程等的使用情况。并且使用图表的方式监控java程序、还具有远程监控能力。

前期准备

1、上传tomcat到虚拟机,webapps下存在Prefteach包

2、监控之前先对jvm加监控参数,在tomcat的bin目录下,catalina.sh文件中,搜索JAVA_OPTS=,在if里面,添加:

  -Dcom.sun.management.jmxremote.port=10086 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.1.101
    以上添加的内容,需要修改两处
   1-改port
   2-改hostname为本机ip

3、启动tomcat并打开输出日志:./startup.sh ../logs/catalina.out

jvisualvm使用

1、windows键+R键 输入jvisualvm回车

2、右键远程添加远程主机

 

3、在 主机ip 上右键添加jmv连接

 

4、输入远程连接的端口号点击确定

5、双击192.168.1.101:10086,打开如下图所示的界面

 

6、进入jvisualvm时时查看程序运行状态

注释:在测试环境中有可能没有权限在服务器上添加需要远程连接的配置,这样只能使用jstack

 
 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics