Home : วิธีการตรวจสอบ memory leak ใน Java application อย่างง่าย โดยใช้โปรแกรม jconsole
Q10067 - HOWTO: วิธีการตรวจสอบ memory leak ใน Java application อย่างง่าย โดยใช้โปรแกรม jconsole

Problem

เราจะรู้ได้อย่างไรว่าโปรแกรมจาวาที่เราเขียนขึ้นนั้นมี memory leak หรือไม่ และจะตรวจสอบอย่างไร ? จะใช้โปรแกรมอะไรในการตรวจสอบ ?

Solution

วิธีง่าย ๆ ในการตรวจสอบว่าโปรแกรมที่เราเขียนนั้นมี memory leak หรือไม่ ก็ทำได้โดยการใช้โปรแกรมที่ชื่อว่า jconsole ซึ่งเป็นโปรแกรมที่มากับ JDK 1.5   jconsole เป็นโปรแกรมที่ใช้ในการ monitor หรือตรวจสอบการทำงานของโปรแกรม ณ runtime เราสามารถจะดูปริมาณ memory ที่ใช้, จำนวน class ที่โหลด, จำนวน thread ที่สร้างขึ้น ณ runtime ได้ ในรูปแบบที่เป็น graphics ทำให้เราดูค่าเหล่านี้ได้ง่ายและสะดวกมากขึ้น

การใช้งาน jconsole มีขั้นตอนดังต่อไปนี้

1. รันโปรแกรมจาวาที่เราเขียนขึ้น โดยระบุ system property com.sun.management.jmxremote เข้าไปด้วย อย่างเช่น

java -Dcom.sun.management.jmxremote -cp ... ClassName

ลอง compile และรันโปรแกรมด้านล่างนี้ ซึ่งจะใช้ memory เพิ่มขึ้นไปเรื่อย ๆ เป็นการจำลองการเกิด memory leak โดยการสร้าง int[] ขนาด 1000 ตัว แล้วเพิ่มเข้าไปใน ArrayList ทุก ๆ 1 วินาที

import java.util.*;
public class TestMemLeak {
   private static List objects = new ArrayList();
   public static void main(String[] args) {
      for (int i = 0; i < 10000; i++) {
         try {
            objects.add(new int[1000]); // เพิ่ม int[] object เข้าไปใน List ทุก ๆ 1s
            System.out.println("# of objects = " + objects.size());
            Thread.sleep(1000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}

รันโปรแกรมตัวอย่าง TestMemLeak ด้วยคำสั่ง

java -Dcom.sun.management.jmxremote TestMemLeak

2. รันโปรแกรม jconsole โดยเรียกใช้คำสั่ง jconsole ที่ command-prompt  (โปรแกรม jconsole จะอยู่ใน JAVA_INSTALL\bin เหมือนกับ javac และ java ถ้าเรากำหนด PATH ไว้แล้วก็สามารถเรียกใช้ได้เลย)

โปรแกรม jconsole จะขึ้นมาทำงาน พร้อมกับแสดงหน้าจอ Connect to Agent เพื่อให้เราเลือก connect ไปหา agent ที่ทำงานอยู่ใน Java VM   ในรูปเราจะเห็น process ของโปรแกรม TestMemLeak อยู่ ให้เราเลือก process ของโปรแกรม TestMemLeak แล้วกด connect (เราจะเห็นเฉพาะ process ของโปรแกรมจาวาที่มีการระบุ system property com.sun.management.jmxremote เอาไว้เท่านั้น)

 

โปรแกรม jconsole จะแสดงหน้าข้อมูลหลักให้เราเลือกว่าจะดูข้อมูลประเภทไหน อย่างเช่น Memory, Thread และClasses   ให้เลือกที่ tab Memory เพื่อดู graph แสดงการใช้ memory ของโปรแกรม ณ runtime

 

จะเห็นว่าโปรแกรม jconsole จะแสดงปริมาณการใช้ memory ของโปรแกรมในรูปของ graph   เส้น graph สีน้ำเงินนี้จะแทนปริมาณ memory ที่ใช้ไปใน heap ณ runtime (เวลาปัจจุบันที่โปรแกรมทำงาน)

 

สังเกตว่า graph จะมีลักษณะเพิ่มขึ้นเรื่อย ๆ และเป็นฟันปลา   ที่ graph มีลักษณะเป็นฟันปลา ก็เพราะว่าจาวามีการทำ GC (garbage collection) เป็นช่วง ๆ เพื่อนำ memory ที่ไม่ได้ใช้กลับมาใช้งานใหม่   graph แบบฟันปลาถือว่าเป็นลักษณะทั่วไปของการใช้ memory ของโปรแกรมจาวา

สังเกตที่จุดต่ำสุดของ graph ในแต่ล่ะช่วง จุดต่ำสุดของ graph แต่ล่ะช่วงจะแสดงให้เห็นถึง memory ที่ยังใช้งานอยู่หลังจากทำ GC  ส่วนระยะระหว่างจุดสูงสุดกับจุดต่ำสุดของแต่ล่ะช่วงจะเป็นปริมาณ memory ที่สามารถเอากลับมาใช้งานใหม่ได้

จุดที่ไม่ปรกติสำหรับ graph นี้ก็คือปริมาณการใช้ memory ของโปรแกรมนั้นเพิ่มขึ้นอย่างต่อเนื่อง สังเกตได้จาก graph ค่อย ๆ สูงขึ้นเรื่อย ๆ และจุดต่ำสุดของการใช้ memory หลังการ GC แต่ล่ะครั้งสูงขึ้นเรื่อย ๆ ถ้าเปรียบเทียบจุดต่ำสุดของแต่ล่ะช่วงจะเห็นว่า เมื่อเวลาผ่านไปจุดต่ำสุดของ memory ที่ใช้ไปนั้นจะเพิ่มขึ้นเรื่อย ๆ  นี่แสดงให้เห็นว่าในการทำ GC ครั้งหลัง ๆ นั้นได้ memory คืนมาน้อยลง นี่เป็นอาการที่แสดงให้เห็นว่าโปรแกรมของเราน่าจะมี memory leak

ในระหว่างที่เราใช้โปรแกรม jconsole เราสามารถสั่งให้ Java VM ทำ GC ได้ด้วย โดย click ที่ปุ่ม Perform GC เราจะเห็นว่าเส้น graph นั้นดิ่งลงอันเป็นผลจากการทำ GC  ให้สังเกตจุดต่ำสุดที่เส้น graph ตกลงด้วย เพื่อดูว่าหลังจากทำ GC แล้วเราได้ memory คืนมามากน้อยแค่ไหน

เมื่อตรวจสอบได้แล้วว่าโปรแกรมเรามี memory leak แล้ว เราคงต้องมา debug ดูอีกทีว่า memory leak นั้นเกิดที่ไหนในโปรแกรมของเรา วิธีพื้นฐานคือไล่ดู collection ต่าง ๆ ที่เป็นตัวแปรแบบ static หรือ instance ว่าลืมปล่อย reference ที่ชี้ objects อยู่ตรงไหนบ้าง  อีกวิธีหนึ่งที่นิยมใช้กันก็คือใช้ profiler tool อย่างเช่น NetBeans profiler ซึ่งจะสามารถบอกเราได้ว่า objects ของ class อะไรที่ทำให้เกิด memory leak และ objects นั้นถูกสร้างที่ตำแหน่งใด วิธีการ debug memory leak โดยใช้ profiler tool คงพูดถึงในบทความอื่นต่อไป 

Related Articles
No Related Articles Available.

Article Attachments
TestMemLeak.java

Related External Links
No Related Links Available.
Help us improve this article...
What did you think of this article?

poor 
1
2
3
4
5
6
7
8
9
10

 excellent
Tell us why you rated the content this way. (optional)
 
Approved Comments...
No user comments available for this article.
Created on 5/29/2007 7:28 PM.
Last Modified on 5/29/2007 8:28 PM.
Last Modified by admin.
Skill Level: Intermediate.
Article has been viewed 1542 times.
Rated 10 out of 10 based on 1 vote.
Print Article
Email Article