دانستنی‌ها

دستورات JDK

در این مقاله، با تعدادی از دستورات مفید و پرکاربرد JDK آشنا می‎شوید.

jps: چاپ JVMهای در حال اجرا

برای نمایش لیست JVMهای در حال اجرا، می‌توانید از دستور jps استفاده کنید. این دستور در جاوا 6 معرفی شده است.

jps

به صورت پیش‌فرض، صرفا PID و نام ساده کلاس راه‌اندازی‌کننده (یا نام JAR راه‌اندازی‌شده) را نمایش می‌دهد.

560   Jps
99714 spring-petclinic-2.0.0.BUILD-SNAPSHOT.jar
95689 CommandServer

البته تعدادی پارامتر اختیاری هم وجود دارد که با استفاده از آن‌ها می‌‌توانید اطلاعات بیشتری کسب کنید.

پارامتر کارکرد
l- نمایش نام کامل کلاس (fully-qualified)، مسیر کامل فایل JAR
v- نمایش آرگومان‌های استفاده‌شده در راه‌اندازی JVM مانند Dxxx-
m- نمایش‌ پارامترهای داده‌شده به اپلیکیشن. مانند args در متد (main(String… args

با توجه به وضعیت سیستم، با فعال بودن تمام پارامترهای بالا، چنین خروجی‌ای حاصل خواهد شد:

99714 target/spring-petclinic-2.0.0.BUILD-SNAPSHOT.jar
679   sun.tools.jps.Jps -lvm -Xms8m \
          -Dapplication.home=/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home
95689 org.asciidoctor.diagram.CommandServer -Djava.awt.headless=true

jinfo: چاپ داده‌های راه‌اندازی‌شده بر روی JVM

برای حل مشکلات production، نیاز است که به یک‌سری اطلاعات اضافی در خصوص یک JVM خاصِ در حال اجرا دسترسی داشته باشیم. این اطلاعات شامل مجموعه‌ای از تمام flagها و آرگومان‌های JVM و همچنین propertyهای سیستم است.

به این منظور، می‌توانید از دستور jinfo استفاده کنید و به اطلاعات تنظیمات جاوا برای یک فرآیند جاوایی خاص دست بیابید.

jinfo 95689

یک نمونه خروجی مربوط به این دستور را در ادامه مشاهده می‌کنید (جهت افزایش خوانایی، کمی خلاصه و فرمت شده است):

Java System Properties:
#Fri Dec 07 16:22:25 CET 2018
    gopherProxySet=false
    awt.toolkit=sun.lwawt.macosx.LWCToolkit
    java.specification.version=11
    sun.cpu.isalist=
    sun.jnu.encoding=UTF-8
    ...
    java.class.version=55.0
    socksNonProxyHosts=local|*.local|169.254/16|*.169.254/16

VM Flags:
    -XX:CICompilerCount=3
    -XX:ConcGCThreads=1
    -XX:G1ConcRefinementThreads=4
    -XX:G1HeapRegionSize=1048576
    -XX:GCDrainStackTargetSize=64
    -XX:InitialHeapSize=268435456
    -XX:MarkStackSize=4194304
    -XX:MaxHeapSize=4294967296
    -XX:MaxNewSize=2576351232
    -XX:MinHeapDeltaBytes=1048576
    -XX:NonNMethodCodeHeapSize=5830092
    -XX:NonProfiledCodeHeapSize=122914074
    -XX:ProfiledCodeHeapSize=122914074
    -XX:ReservedCodeCacheSize=251658240
    -XX:+SegmentedCodeCache
    -XX:+UseCompressedClassPointers
    -XX:+UseCompressedOops
    -XX:+UseFastUnorderedTimeStamps
    -XX:+UseG1GC

VM Arguments:
    jvm_args:
        -Djava.awt.headless=true
    java_command:
        org.asciidoctor.diagram.CommandServer
    java_class_path (initial):
        ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/server-1.3.13.jar:
        ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/ditaa-1.3.13.jar:
        ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/ditaamini-0.11.jar:
        ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/plantuml-1.3.13.jar:
        ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/plantuml.jar:
        ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/jlatexmath-minimal-1.0.5.jar:
        ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/asciidoctor-diagram-1.5.9/lib/batik-all-1.7.jar
Launcher Type: SUN_STANDARD

به منظور محدود و فیلتر کردن خروجی، پارامترهای زیر وجود دارد:

پارامتر کارکرد
flags- صرفا اطلاعات مرتبط با flag را نمایش می‌دهد.
sysprops- صرفا propertyهای سیستم را نمایش می‌دهد.

در قدم بعدی، لازم است دیدی نسبت به داده‌های مرتبط با کلاسِ روی JVM به دست بیاورید. مانند آمارهای مربوط به بارگذاری کلاس، اشیای در انتظار finalizeشدن و heap اشیا.

می‌توانید از دستور jmap برای جاپ جزییات یک فرآیند خاص استفاده کنید. بسته به پارامتر مورد استفاده، خروجی متفاوت خواهد بود.

جهت چاپ آمار کلاس بارگذاری‌شده:

jmap -clstats 95689
Index Super InstBytes KlassBytes annotations   CpAll MethodCount Bytecodes MethodAll   ROAll    RWAll    Total ClassName
    1    -1   1686600        504           0       0           0         0         0      24      616      640 [B
    2    -1    485288        504           0       0           0         0         0      24      616      640 [I
    3    20    420984        616         128   14224         109      4577     64472   18640    62104    80744 java.lang.String
    4    -1    375216        504           0       0           0         0         0      24      616      640 [C
    5    20    374448        672           0   22120         139      5682     46936   24616    47008    71624 java.lang.Class
    6    -1    238888        504           0       0           0         0         0      24      616      640 [Ljava.lang.Object;
    7    20    165440        584           0    1392           7       149      1864    1152     3008     4160 java.util.HashMap$Node
    8    20    141856        592           0    1368           9       213      2776    1488     3584     5072 java.util.concurrent.ConcurrentHashMap$Node
    9    20     71120        584           0    1400           7       171      2264    1208     3384     4592 java.util.TreeMap$Entry
...
 3085  3084         0        632           0     808           5        71       960     640     1920     2560 sun.util.resources.TimeZoneNamesBundle
 3086    20         0        600           0    1256           5       159      1000     856     2264     3120 sun.util.resources.provider.NonBaseLocaleDataMetaInfo
              5147912    1947360       10656 6473512       31831   1647775   9869272 6170712 13100408 19271120 Total
                26.7%      10.1%        0.1%   33.6%           -      8.6%     51.2%   32.0%    68.0%   100.0%
Index Super InstBytes KlassBytes annotations   CpAll MethodCount Bytecodes MethodAll   ROAll    RWAll    Total ClassName
جهت چاپ هیستوگرام heap اشیای جاوایی:
jmap -histo 95689
 num     #instances         #bytes  class name (module)
-------------------------------------------------------
   1:       2578716      182530328  [I (java.base@11.0.1)
   2:        261988       71251184  [Z (java.base@11.0.1)
   3:        798811       57514392  java.util.regex.Matcher (java.base@11.0.1)
   4:        413769       28433240  [B (java.base@11.0.1)
   5:        296086       26055568  java.util.regex.Pattern (java.base@11.0.1)
   6:        301073       16858024  [Ljava.lang.Object; (java.base@11.0.1)
   7:        276719       15496264  [Ljava.util.regex.Pattern$GroupHead; (java.base@11.0.1)
   8:        798811       13032760  [Ljava.util.regex.IntHashSet; (java.base@11.0.1)
   9:        318781        7650744  java.util.regex.Pattern$BmpCharProperty (java.base@11.0.1)
  10:        289648        6951552  java.util.ArrayList (java.base@11.0.1)
...
1616:             1             16  sun.util.logging.PlatformLogger (java.base@11.0.1)
1617:             1             16  sun.util.resources.LocaleData$LocaleDataStrategy (java.base@11.0.1)
1618:             1             16  sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo (jdk.localedata@11.0.1)
Total      10605127      526098920

این دستور برای تشخیص نشت حافظه نیز استفاده می‌شود که قبلا در مقاله‌ای مجزا، به تفصیل توضیح داده شده است.

jstack: چاپ نخ‌های موجود بر روی JVM

اگر مشکل مربوط به نخ‌ها (threads) باشد (مانند مشکل deadlock یا livelock)، جزییات مربوط به نخ‌های در حال اجرا، در دسترس هستند.

می‌توانید از دستور jstack استفاده کرده و stack trace مربوط به یک فرآیند جاوایی خاص را ببینید.

jstack 95689
2018-12-07 19:06:01
Full thread dump OpenJDK 64-Bit Server VM (11.0.1+13 mixed mode):

Threads class SMR info:
_java_thread_list=0x00007fd1212fb270, length=13, elements={
0x00007fd120015800, 0x00007fd120051000, 0x00007fd120053800, 0x00007fd11e89c000,
0x00007fd120045800, 0x00007fd11f00f800, 0x00007fd12004a800, 0x00007fd11e8d9800,
0x00007fd120065000, 0x00007fd11f883000, 0x00007fd11f075800, 0x00007fd11ed4b000,
0x00007fd11f30e800
}

"main" #1 prio=5 os_prio=31 cpu=314567.92ms elapsed=2035.03s tid=0x00007fd120015800 nid=0x2403 runnable  [0x000070000bbac000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(java.base@11.0.1/Native Method)
	at java.net.SocketInputStream.socketRead(java.base@11.0.1/SocketInputStream.java:115)
	at java.net.SocketInputStream.read(java.base@11.0.1/SocketInputStream.java:168)
	at java.net.SocketInputStream.read(java.base@11.0.1/SocketInputStream.java:140)
	at java.io.BufferedInputStream.fill(java.base@11.0.1/BufferedInputStream.java:252)
	at java.io.BufferedInputStream.read(java.base@11.0.1/BufferedInputStream.java:271)
	- locked <0x00000007000d0558> (a java.io.BufferedInputStream)
	at org.asciidoctor.diagram.HTTPInputStream.readLine(HTTPInputStream.java:20)
	at org.asciidoctor.diagram.HTTPInputStream.readRequest(HTTPInputStream.java:56)
	at org.asciidoctor.diagram.CommandServer.processRequests(CommandServer.java:61)
	at org.asciidoctor.diagram.CommandServer.main(CommandServer.java:25)

...

"process reaper" #109 daemon prio=10 os_prio=31 cpu=538.50ms elapsed=1683.17s tid=0x00007fd11f30e800 nid=0x6507 waiting on condition  [0x000070000ba4e000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at jdk.internal.misc.Unsafe.park(java.base@11.0.1/Native Method)
	- parking to wait for  <0x000000070016fe20> (a java.util.concurrent.SynchronousQueue$TransferStack)
	at java.util.concurrent.locks.LockSupport.parkNanos(java.base@11.0.1/LockSupport.java:234)
	at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(java.base@11.0.1/SynchronousQueue.java:462)
	at java.util.concurrent.SynchronousQueue$TransferStack.transfer(java.base@11.0.1/SynchronousQueue.java:361)
	at java.util.concurrent.SynchronousQueue.poll(java.base@11.0.1/SynchronousQueue.java:937)
	at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@11.0.1/ThreadPoolExecutor.java:1053)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@11.0.1/ThreadPoolExecutor.java:1114)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@11.0.1/ThreadPoolExecutor.java:628)
	at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)

"VM Thread" os_prio=31 cpu=1139.30ms elapsed=2035.01s tid=0x00007fd11f88e000 nid=0x4b03 runnable

"GC Thread#0" os_prio=31 cpu=1888.39ms elapsed=2035.03s tid=0x00007fd11e805000 nid=0x5203 runnable

"GC Thread#1" os_prio=31 cpu=1951.89ms elapsed=2034.53s tid=0x00007fd11e8e1800 nid=0x9903 runnable

"GC Thread#2" os_prio=31 cpu=1897.20ms elapsed=2034.53s tid=0x00007fd11e8e2800 nid=0x5f03 runnable

"GC Thread#3" os_prio=31 cpu=1901.78ms elapsed=2034.53s tid=0x00007fd11e90d000 nid=0x6103 runnable

"G1 Main Marker" os_prio=31 cpu=0.57ms elapsed=2035.03s tid=0x00007fd11e84a000 nid=0x5003 runnable

"G1 Conc#0" os_prio=31 cpu=36.31ms elapsed=2035.03s tid=0x00007fd11e84a800 nid=0x3003 runnable

"G1 Refine#0" os_prio=31 cpu=8.48ms elapsed=2035.03s tid=0x00007fd11f882000 nid=0x3203 runnable

"G1 Refine#1" os_prio=31 cpu=2.95ms elapsed=2034.52s tid=0x00007fd11e9b1000 nid=0x9703 runnable

"G1 Refine#2" os_prio=31 cpu=0.06ms elapsed=2034.36s tid=0x00007fd11f939800 nid=0x6303 runnable

"G1 Young RemSet Sampling" os_prio=31 cpu=898.32ms elapsed=2035.03s tid=0x00007fd11e858800 nid=0x3303 runnable
"VM Periodic Task Thread" os_prio=31 cpu=933.68ms elapsed=2034.94s tid=0x00007fd11f00c800 nid=0xa603 waiting on condition

JNI global refs: 98, weak refs: 5

برای چک کردن قفل‌ها، از پارامتر l- استفاده کنید. به این ترتیب، خروجی زیر چاپ خواهد شد:

...
"main" #1 prio=5 os_prio=31 cpu=489307.36ms elapsed=3019.58s tid=0x00007fd120015800 nid=0x2403 runnable  [0x000070000bbac000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(java.base@11.0.1/Native Method)
	at java.net.SocketInputStream.socketRead(java.base@11.0.1/SocketInputStream.java:115)
	at java.net.SocketInputStream.read(java.base@11.0.1/SocketInputStream.java:168)
	at java.net.SocketInputStream.read(java.base@11.0.1/SocketInputStream.java:140)
	at java.io.BufferedInputStream.fill(java.base@11.0.1/BufferedInputStream.java:252)
	at java.io.BufferedInputStream.read(java.base@11.0.1/BufferedInputStream.java:271)
	- locked <0x00000007000d0558> (a java.io.BufferedInputStream)
	at org.asciidoctor.diagram.HTTPInputStream.readLine(HTTPInputStream.java:20)
	at org.asciidoctor.diagram.HTTPInputStream.readRequest(HTTPInputStream.java:56)
	at org.asciidoctor.diagram.CommandServer.processRequests(CommandServer.java:61)
	at org.asciidoctor.diagram.CommandServer.main(CommandServer.java:25)

   Locked ownable synchronizers: //1
	- None

"Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.94ms elapsed=3019.55s tid=0x00007fd120051000 nid=0x3603 waiting on condition  [0x000070000c2c1000]
   java.lang.Thread.State: RUNNABLE
	at java.lang.ref.Reference.waitForReferencePendingList(java.base@11.0.1/Native Method)
	at java.lang.ref.Reference.processPendingReferences(java.base@11.0.1/Reference.java:241)
	at java.lang.ref.Reference$ReferenceHandler.run(java.base@11.0.1/Reference.java:213)

   Locked ownable synchronizers: //1
	- None
...

1: همانطور که می‌بینید، هیچ قفلی وجود ندارد!

jconsole: نظارت بر یک JVM

داشتن یک دید بصری از داخل JVM در حال اجرا، می‌تواند بسیار مفید باشد.

با استفاده از دستور jconsole یک کنسول گرافیکی باز می‌شود که برای نظارت و مدیریت اپلیکیشن‌های جاوایی می‌توانید از آن بهره ببرید.

jconsole یکی از مهم‌ترین ابزارهای توسعه‌دهندگان جاوا است.

این ابزار، در زمینه‌های مختلفی مانند آنچه در ادامه ذکر شده، دیدی بصری از یک JVM در حال اجرا به شما می‌دهد.

حافظه:

در این کنسول، می‌توان نمودارهای مختلف مرتبط با حافظه مانند heap یا non-heap یا old gen یا eden یا survivor یا … را دید.

نخ‌ها:

در JConsole می‌توان روند تعداد نخ‌ها در یک بازه زمانی دلخواه را مشاهده کرد. هم‌چنین می‌توان هر نخ را به صورت جداگانه به همراه نام، وضعیت و پشته‌اش (stack) مشاهده کرد.

کلاس‌ها:

تعداد کلاس‌های بارگذاری‌شده را هم می‌توان دید.

خلاصه VM:

این ابزار می‌تواند داده‌های مرتبط با JVM را به ما نشان دهد. مانند

  • آرگومان‌های VM
  • Class path
  • Library path
  • Boot class path
  • سایز Heap
  • غیره
MBeans:

JConsole قادر است تمام Mbeanهای در دسترس را در یک ساختار درختی شامل ویژگی‌ها و متدهایشان نمایش دهد. علاوه بر این، امکان مقداردهی به ویزگی‌ها و یا فراخوانی متدها را هم به ما می‌دهد.

جمع‌بندی

JDK تعداد زیادی ابزار برای کمک به توسعه‌دهندگان دارد. چه از یک IDE استفاده کنید چه نکنید، این ابزارها کمکی بزرگ در کارهای روزانه‌تان هستند.

منبع

.

.

.

با ما همراه باشید

آدرس کانال تلگرام: JavaCupIR@

آدرس اکانت توییتر: JavaCupIR@

آدرس صفحه اینستاگرام: javacup.ir

آدرس گروه لینکدین: Iranian Java Developers

نوشته های مشابه

‫3 دیدگاه ها

  1. شکرا
    سوالی درمورد enum ذهنم را مشغول کرده اگر اساتید مشکل گشایی کنند ممنون می گردم .
    در جاوا کلاس های بسیاری وجود دارد مثل دیتا استراکچر ها ، استریم ها ، کلاس های ریاضی گرافیکی و غیره و در مورد همه آنها با ایجاد یک شی می توانیم از آن کلاس و متد ها و قابلیت های آن استفاده نماییم در نتیجه ما با شی ای از آن کلاس ها سروکار داریم .
    در مورد enum ولی ما خود یک کلاس می سازیم (با اینکه کلاس enum در جاوا وجود دارد ) و نه شی ای از آن کلاس enum .
    خوب enumی که ما می سازیم یک کلاس است پس پیش فرض اینگونه درنظر می گیریم که کلاس enum که ما می سازیم می بایست کلاس enum جاوا را extend کند ولی می دانیم که ساختن enum به هیچ وجه بدینگونه نیست و فقط با نوشتن enum و دادن نام دلخواه کلاس ساخته می شود .
    آیا کلاس enum ما بصورت ضمنی کلاس enum جاوا را ارثبری می کند ؟
    اگر جواب سوال قبل بلی باشد از کدام متد آن استفاده می کند که بدین گونه عجیب اشیا را درون خود تعریف می کند در جاواداک چنین متدی مشاهده نکردم .
    در جاواداک کلاس enum کانستراکتور دارد چرا نمی توانیم از کانستراکتور آن استفاده نماییم (مثلا به شکل new )؟
    ودر نهایت اینکه چرا کلاس enum متد finalize را بسته است ؟
    پیشاپیش سپاسگزارم

    1. سلام تا اونحایی که بنده اطلاع داره کلاسی به نام Enum داریم که یک کلاس جنریک هست
      در واقع شما وفتی یک enum برای مثال BOOK میسازی داری یک کلاس میسازی که از Enum ارث بری میکنه و متدی مثل name هم از اون کلاس اومده

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا