วันอาทิตย์ที่ 26 มิถุนายน พ.ศ. 2559

เพิ่ม PermGen space เพื่อให้ IDE ทำงานสะดวก...และไม่สะดุด



เคยไหม...ที่ทุกครั้ง เวลาที่เราเขียน Code บน NetBean หรือ Eclipse แล้วค้างๆๆๆๆๆ หรือ Deploy แล้วค้างแล้ว Dump ขึ้นตัวแดงมาเลยย... แล้วก็อ้างว่าเครื่องเก่าบ้าง กากบ้าง ต้องไปเพิ่ม Ram ให้เยอะขึ้น

จากการที่ท๊อปได้เข้าไปอ่านตาม Blog ต่างๆ เขาสรุปสาเหตุไว้ ดังนี้...

1. ปัญหาจากช่วง Deploy และ Undeploy 

-ช่วง runtime แต่ละ application จะถูกโหลดผ่านทาง application classloader โดยทำหน้าที่ โหลดไฟล์ .class จาก jar files และเมื่อ undeploy application นั้น classloader มันจะทำการละทิ้ง class ที่ได้มีการโหลดเข้ามา แล้วจะถูกจัดการโดย garbage collector ต่อมาในภายหลังเพื่อคืนทรัพยากรสู่ระบบ

และจากเหตุการณ์ตรงนี้แหละ....

-บางครั้ง classloader อาจยังมีการเก็บบางสิ่งที่ถูกโหลดเข้ามาไว้อยู่ และปกป้องมันจาก garbage collector เนื่องจากว่ามันอาจจะถูกใช้งานอยู่ ทำให้ garbage collector ไม่สามารถเข้ามาจัดการได้ จึงเป็นเหตุทำให้เกิดข้อผิดพลาด java.lang.OutOfMemoryError: PermGen space ได้
2. ปัญหาจากการจัดการ Memory ใน VM

-เดิมที memory ที่มีอยู่ใน Virtual Machine (VM) จะถูกหารไปใช้งานโดย number of region ซึ่งหนึ่งในนั้น คือ region ที่เป็น PermGen space (permanent generation space) ซึ่งเป็นพื้นที่ของ memory สำหรับโหลด class file เข้ามา

-สำหรับ size of memory region นั้น จะมีการกำหนดไว้อย่างคงที่โดยไม่มีการเปลี่ยนแปลงเมื่อ VM ทำงานอยู่ เราสามารถกำหนด size of region โดย -XX:MaxPermSize เช่น -XX:MaxPermSize = 256m หมายความว่า เรากำหนด size of memory region สูงสุดที่ 256 MB โดยหากเราไม่มีการกำหนด โดยพื้นฐานแล้วทางจะมีการกำหนดไว้ที่ 64 MB

3. ปัญหาจาก garbage collector 

-เนื่องจาก garbage collector ไม่สามารถคืนทรัพยากรสู่ระบบได้

วิธีการที่ garbage collector จัดการ... คือ ต้องเก็บ classes ใหม่ที่กำลังโหลดเข้ามาใน memory เป็นเหตุทำให้ VM นั้นเกิดการขาดแคลน space ใน memory region จึงต้องมี JAVA heap ไว้เพื่อช่วยจัดสรร memory ให้เพียงพอต่อ size of Object ที่อาศัยอยู่บน process heap

ปัญหาที่เกิดตามมา ก็คือ... เกิด Object นั้นออกจาก process และคืน memory สู่ระบบ

-เนื่องจากว่า JAVA application จะทำงานตาม process เดี่ยวๆ ของแต่ละ process ที่ทำงานอยู่ โดยจะไม่มีการแชร์ memory ร่วมกันระหว่าง process ซึ่งแต่ละ process จะถูกจัดสรร memory ให้แต่ละ process เองโดย JVM ที่เรียกว่า process heap 

เพราะฉะนั้น... การตั้งค่าพารามิเตอร์ –Xmx นั้นไม่ได้ช่วยอะไรมาก โดยพารามิเตอร์ดังกล่าว เป็นเพียงการกำหนด size of total heap เท่านั้น และไม่ได้ส่งผลกระทบอะไรต่อ size of PermGen region เลย

หลักๆ คือ ... 

-PermSize ไม่เพียงพอต่อการโหลด class file มาเก็บไว้ใน memory PermGen space 

สิ่งที่ต้องทำ คือ ...

-กำหนดค่า PermGen space และ heap size ให้เพียงพอต่อความต้องการใช้งาน

โดยทั่วไปเราจะกำหนด Environment Variables จาก JAVA_OPTS ซึ่งเป็น variable name ไว้กำหนดค่าต่างๆ ดังนี้

JAVA_OPTS="–Xms256m  -Xmx512m  -XX:PermSize=256m -XX:MaxPermSize=512m "

–Xms (initial java total heap size) ในกรณีที่เกิดปัญหาทำงานช้า
-Xmx : maximum java total heap size
-XX:PermSize : initial permanent  generation  space
-XX:MaxPermSize : maximum permanent generation space

นอกจากนี้ ยังมีพารามิเตอร์ตัวอื่นที่น่าสนใจ เช่น

-Xss128m เป็นการกำหนด stack size เท่ากับ 128MB
-ในแต่ละ thread ใน VM นั้น จะมี stack อยู่ โดย stack size จะจำกัดจำนวนของ thread ไว้ตามที่เราจะสามารถมีได้
ดังนั้น ถ้าจำนวนของ thread > stack size จะทำให้ขาดแคลน memory ตามที่แต่ละ thread มันต้องการ

-Xmn100m เป็นการกำหนด size of the heap สำหรับ young generation เท่ากับ 100MB
-memory ที่ถูกใช้งานโดย JVM จะถูกจัดเป็น generation

-ขั้นที่ 1 : generation จะแบ่งตามช่วงเวลาที่ memory pool นั้นได้ถือครอง object ในช่วงเวลาแตกต่างกันออกไป  โดย object ใหม่ที่ถูกเรียกเข้ามาใช้งานนั้นจะมีการจอง memory เพื่อใช้งานใน young generation region (บางครั้งอาจจะเรียกว่า new generation region) เมื่อไม่ได้ใช้งานจะถูกนำไปเก็บไว้ที่ memory old generation region 

-ขั้นที่ 2 : หาก memory young generation region เต็มแล้ว garbage collector จะทำการเรียกคืนหน่วยจำส่วนหนึ่ง ที่ไม่ได้มีการใช้งานแล้ว จาก old generation region แบ่งไปให้กับ young generation region

เดิมทีนั้น จะมีการแบ่ง generation ของ total heap size ต่อมาได้มีการแบ่ง old generation ออกมาเป็น tenured generation หลังจากที่ generational memory system นั้นได้ทำการหาร heap เข้าไป ใน sized partitions ที่ถูกแบ่งไว้อย่างระมัดระวังจะถูกเรียกว่า generation

–Xmn จะกำหนด size of the heap ที่ถูกจัดสรรสำหรับ Eden generation of the heap เพราะเริ่มแรก object ที่มีการใช้งานจะจอง memory เบื้องต้นบน Eden ก่อนที่จะถูกนำไปเก็บบน memory ทั้ง 2 spaces ระหว่าง survivor spaces จนกระทั่งมันไม่ได้ถูกเรียกใช้งาน และถูกนำไปเก็บไว้ยัง old generation region

older  generation = (ขนาดของ -Xmx) – (ขนาดของ -Xmn) 
-ดังนั้น... –Xmn จะต้องมีค่าต่ำกว่า –Xmx เสมอ

โดยทั่วไปเราไม่ต้องการ Eden ที่ใหญ่เกินไป หรือใช้มากกว่าที่ garbage collector จะเรียกคืนสู่ระบบได้ จึงไม่จำเป็นต้องตั้งค่าให้กับพารามิเตอร์ -Xmn เพิ่มก็ได้ 

-นอกจากนี้ ก็มีการแนะนำต่ออีกว่า... ควรเลือก JDK ให้เหมาะสมกับ OS เพราะ OS 64 bit  จะมี heap size default มากกว่า OS 32 bit เพื่อรองรับ size of object ที่ใหญ่ขึ้น

Keywork : JAVA Performance Tuning, Java Concurrency in Practice

Refference : 

-เรื่อง Dealing with “java.lang.OutOfMemoryError: PermGen space” error
http://stackoverflow.com/questions/88235/dealing-with-java-lang-outofmemoryerror-permgen-space-error

-เรื่อง Tomcat – java.lang.OutOfMemoryError: PermGen space
http://www.mkyong.com/tomcat/tomcat-javalangoutofmemoryerror-permgen-space/

-เรื่อง java.lang.OutOfMemoryError: Permgen space
https://plumbr.eu/outofmemoryerror/permgen-space
top.sk Web Developer

I can design web applications by using Java Server Faces (JSF), Primefaces, EJB3, SQL, DB2 (IBM) and designing report (Word, Excel and PDF) by using XML Script and Crystal Clear Report for the organization that can be easily and no problem for used and they can use the Web to manage the customer's organization effectively. I want to learn a new culture, technology and colleagues involved in the IT profession.

ไม่มีความคิดเห็น :

แสดงความคิดเห็น