Friday, August 17, 2018

Learning the Spring Expression Language (SpEL)


"The Spring Expression Language (abbreviated as SpEL) is a powerful expression language. Within the Spring portfolio, it serves as the foundation for expression evaluation. It supports querying and manipulating an object graph at runtime. It can be used with both XML-based and annotation-based Spring configurations and bean definitions. Since it is capable of assigning value dynamically at runtime, it can save us a lot of code." ... ... ...


The article written by me was published in DZone on 10 August, 2018. To read the full article, please use the following link:
Learning the Spring Expression Language (SpEL)


Thursday, July 19, 2018

ApplicationContext of Spring

Context
Context is the larger surrounding part which can have influence on the current unit of work. It can be the running environment, the environment variables, instance variables, local variables, state of other classes etc. For example, ServletContext represents the servlet’s environment within servlet container. Similarly, ApplicationContext represents Spring’s environment within Spring container. More examples of context are JSF's FacesContext, Android's Context, JNDI's InitialContext etc. The context implementation usually follow the Facade Pattern which hides the complexities of the larger system and provides a simpler interface to the client.

ApplicationContext
The ApplicationContext is the central interface of Spring application. It provides configuration information to the application. It is read-only at run time, but can be reloaded if necessary. A number of classes implement the ApplicationContext interface, allowing for a variety of configuration options and types of applications.

ApplicationContext is the context initialized by ContextLoaderListener that we define in our application’s web.xml file. There will be only one application context per web application. We can explicitly declare the context configuration file name in web.xml using the contextConfigLocation param. Otherwise, Spring will search for the file applicationContext.xml under WEB-INF folder. The configuration would look something like this:
 
<listener>    
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/root-context.xml</param-value>
</context-param>
In the above configuration, we are using the file root-context.xml and Spring will create an ApplicationContext from it.

WebApplicationContext
WebApplicationContext is the servlet specific context. Each DispatcherServlet is associated with a single WebApplicationContext. Dispatcher servlets are also configured in the application’s web.xml file. Each dispatcher servlet can be initialized from <servlet-name>-servlet.xml file, which is the default file name pattern.  Multiple DispatcherServlets allow us to categorize the incoming requests based on the url-pattern of servlet and handle them accordingly. For example, one dispatcher servlet can help serving the web pages via Controller, while another servlet can be used to implement a stateless REST web service.
To change the configuration file of dispatcher-servlet, we can use init-param with contextConfigLocation as param-name, like the following:
<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/sample-dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
    
<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
In the above configuration, Spring will not find dispatcher-servlet context file with the name mvc-dispatcher-servlet.xml, but it will look for the file name sample-dispatcher-servlet.xml because it is specified as the init-param value for contextConfigLocation

Difference between ApplicationContext and WebApplicationContext
ApplicationContext is the root-context, which has bean configurations that can be used across the entire application as singletons. There is always a single application context in a web application. But, there can be multiple WebApplicationContexts for each of the dispatcher servlets that we specify in application’s web.xml.
It’s always better to keep a clear separation between middle-tier services and web-related components.  Middle-tier services like business logic components and data access classes are preferred to be defined in the ApplicationContext. Web-related components such as controllers and view-resolvers are preferred to be defined in the respective dispatcher-servlet‘s WebApplicationContext.

References 
http://www.jcombat.com/spring/applicationcontext-webapplicationcontext
https://spring.io/understanding/application-context
http://codesenior.com/en/tutorial/Spring-ContextLoaderListener-And-DispatcherServlet-Concepts
https://schoudari.wordpress.com/2012/07/23/purpose-of-contextloaderlistener-spring-mvc/
https://stackoverflow.com/questions/11815339/role-purpose-of-contextloaderlistener-in-spring

Sunday, May 27, 2018

Introduction to the Apache POI Library

"We use Office applications frequently to serve many purposes. Have you ever thought of doing the task of reading or writing an Office file (like Excel spreadsheet) programmatically? Sometimes, there will be situations where we will have to handle it by writing some custom program. The Apache POI library is a very helpful tool to accomplish such a task. The POI library can be used for reading or writing all kinds of Office documents. This article, however, will focus on working with spreadsheet files — more specifically, Excel files." ... ... ...

The article written by me was published in DZone on 22 May, 2018. To read the full article, please use the following link:
Introduction to the Apache POI Library

Saturday, March 31, 2018

জাভা মেমরি ম্যানেজমেন্ট: গারবেজ কালেকশন

এই ব্লগটি জাগবিডিতে ১৫ ফেব্রুয়ারি, ২০১৮ তারিখে প্রকাশিত হয়েছিলো, পাওয়া যাবে এই লিংকে
 
জাভা মেমরি ম্যানেজমেন্ট বা গারবেজ কালেকশন সম্পর্কে আমাদের আসলে কেন জানা দরকার? যেসব অ্যাপলিকেশনে অনেক ডাটা নিয়ে একসাথে কাজ করতে হয়, যেসব অ্যাপলিকেশনে স্বাভাবিকভাবেই বেশি মেমরি ব্যবহার করতে হয়। প্রডাকশন সার্ভারে রিসোর্স হিসেবে মেমরির একটা সীমাবদ্ধতা থাকে। তাই একটু বেশি মেমরি ব্যবহার করতে গেলে মেমোরি লিক হবার সম্ভাবনা বেড়ে যায়, "আউট অফ মেমোরি ইরর" একসেপসন (OutOfMemoryError Exception) পাবার সম্ভাবনা থাকে। আর সত্যিই মেমোরি লিক হলে অ্যাপলিকেশন সার্ভার ক্রাশ করে যাবে। এ ধরনের পরিস্থিতি সামাল দেয়ার জন্য বা এড়ানোর জন্য তাই মেমরি ম্যানেজমেন্ট সম্পর্কে জানা দরকার। গারবেজ কালেকশন কিভাবে কাজ করে, তা কিভাবে মনিটর করা যায়, কিভাবে টিউন করা যায় এগুলো নিয়ে জানতে হবে।

গারবেজ কালেকশন কি ও কিভাবে কাজ করে
জাভাতে যে অবজেক্টগুলো আর ব্যবহৃত হচ্ছে না, বা যেগুলোর আর কোন রেফারেন্স নেই, সেগুলোকে হিপ মেমরি থেকে খালি করে দেয়া হয়। এই প্রক্রিয়াটি জেভিএমে স্বয়ংক্রিয়ভাবে হয়ে থাকে, যা গারবেজ কালেকশন নামে পরিচিত। এটা নিশ্চিত করে যেন নতুন অবজেক্ট তৈরি করার জন্য পর্যাপ্ত খালি মেমরি পাওয়া যায়। এটা নিঃসন্দেহে জাভার একটি বড় সুবিধা।

মূলত তিনটি ধাপে গারবেজ কালেকশনের কাজ সম্পন্ন হয়। সর্বপ্রথম অব্যবহৃত অবজেক্টগুলো খুঁজে বের করা হয়। এরপর সেই অব্যবহৃত অবজেক্টগুলো হিপ মেমরি থেকে মুছে ফেলা হয়। অর্থাৎ, অব্যবহৃত অবজেক্টগুলোর দখল করা সমস্ত মেমরি খালি করে দেয়া হয়। সবশেষে, হিপ মেমরির বেঁচে থাকা অবজেক্টগুলো যেগুলো মেমরিতে ছড়িয়ে ছিটিয়ে আছে, সেগুলো সব একসাথে করে রাখা হয় বা কমপ্যাক্ট (Compact) করা হয়। কমপ্যাক্ট করার কাজটি করা হয় ভালো পারফরমেন্স পাবার জন্য। এই ধাপগুলোকে একত্রে মার্ক-সুইপ-কমপ্যাক্ট (mark-sweep-compact) পদ্ধতি বলা হয়।

মেমরি কমপ্যাক্ট করা

বিভিন্ন গারবেজ কালেকটর (ব্যাকগ্রাউন্ড প্রোগ্রাম যা মূলত গারবেজ কালেকশনের কাজ করে থাকে) বিভিন্ন পদ্ধতি বা এলগরিদম ব্যবহার করে এই ধাপগুলো বাস্তবায়ন করে থাকে। এসম্পর্কে আমরা পরে আরো আলোচনা করবো।

মেমোরি মডেল
গারবেজ কালেকশন নিয়ে জানতে হলে আমাদের প্রথমে জে.ভি.এম. এর মেমোরি মডেল সম্পর্কে জানতে হবে। জে.ভি.এম. মেমরির যে অংশে অ্যাপলিকেশনের সব অবজেক্টগুলো রাখা হয় তাকে বলে হিপ মেমরি। হিপ মেমরির বিভিন্ন অংশ সম্পর্কে জানা যাক।

জে.ভি.এম. মেমোরির বিভিন্ন অংশ

হিপ মেমরিকে মোটা দাগে দুই ভাগে ভাগ করা যায়: ১। ইয়ং জেনারেশন বা নার্সারি স্পেস এবং ২। ওল্ড জেনারেশন বা টেনিউরড স্পেস । ইয়ং জেনারেশনকে আবার ভাগ করা হয় এডেন স্পেস আর দুটো সারভাইভর স্পেসে। হিপ মেমরি ছাড়া জে.ভি.এম. মেমরিতে পার্মানেন্ট জেনারেশন নামের অংশ আছে, যেখানে অ্যাপলিকেশন মেটাডাটা (মেথড, ক্লাস সম্পর্কিত ডাটা) থাকে।

ইয়ং জেনারেশন ও মাইনর জিসি
নতুন তৈরি হওয়া অবজেক্টগুলো থাকে এডেন স্পেসে। এডেন স্পেস যখন অবজেক্টে পরিপূর্ণ হয়ে যায়, তখন একটা মাইনর গারবেজ কালেকশন (Minor GC) সম্পন্ন হয় এবং বেঁচে যাওয়া অবজেক্টেগুলো সারভাইভার স্পেসে সরিয়ে আনা হয়। একটা সারভাইভার স্পেস পরিপূর্ণ হয়ে গেলে অবজেক্টগুলো অন্য সারভাইভার স্পেসে সরিয়ে আনা হয়। এটা মনে রাখতে হবে যে, একটা সারভাইভর স্পেস সব সময়ই খালি রাখা হয়।

ফুল জিসি
সাধারণভাবে অনেক সময় মেজর জিসিকেই ফুল জিসি (Full GC) হিসেবে অভিহিত করা হয়। বিস্তারিতভাবে বলতে গেলে, ফুল জিসি সম্পন্ন হওয়া মানে হল পুরো হিপ মেমরি ক্লিন করা, অর্থাৎ ইয়ং জেনারেশন ও ওল্ড জেনারেশন দুটোই ক্লিন করা। ফুল জিসিতে পার্মানেন্ট জেনারেশনও ক্লিন করা হয়।

পারফরমেন্সের সাথে সম্পর্ক
একটা খুব গুরুত্বপূর্ণ বিষয় আমাদের মনে রাখতে হবে যে, গারবেজ কালেকশনকে "স্টপ দি ওয়ার্ল্ড" (Stop the world) ইভেন্ট বলা হয়। তার মানে হল, যখন গারবেজ কালেকশনের কাজ চলতে থাকে, তখন সকল অ্যাপ্লিকেশন থ্রেড বন্ধ থাকে। মাইনর জিসিতে সময় কম লাগে কারণ ইয়ং জেনারেশনে অবজেক্টেগুলো কম সময়ের জন্য থাকে। যেজন্য অ্যাপ্লিকেশান এর প্রভাব কম। কিন্তু মেজর জিসিতে সময় অনেক বেশি লাগে, একারণে অ্যাপ্লিকেশন বেশি সময়ের জন্য রেসপন্স করা থেকে বিরত থাকে। তাই মেজর জিসি বেশি করে হলে অ্যাপ্লিকেশনের পারফরমেন্স কমে যাবে।

হিপ মেমরি সংক্রান্ত জেভিএম অপশন
জাভা অ্যাপ্লিকেশান চালানোর সময় আমরা অনেক রকম জেভিএম অপশন (JVM option) বা আর্গুমেন্ট ব্যবহার করতে পারি। এর মধ্যে কতগুলো রয়েছে হিপ মেমরির সাথে সম্পর্কিত। গুরুত্বপূর্ণ কতগুলো হিপ মেমরি সংক্রান্ত জেভিএম অপশনগুলো হলঃ
  • -Xms   নির্ধারণ করে জেভিএম শুরু হবার সময় প্রাথমিক হিপ সাইজ
  • -Xmx   নির্ধারণ করে সর্বোচ্চ হিপ সাইজ
  • -Xmn   নির্ধারণ করে ইয়ং জেনারেশনের সাইজ
  • -XX:PermGen   নির্ধারণ করে পার্মানেন্ট জেনারেশনের প্রাথমিক সাইজ
  • -XX:MaxPermGen   নির্ধারণ করে পার্মানেন্ট জেনারেশনের সর্বোচ্চ সাইজ
  • -XX:SurvivorRatio   নির্ধারণ করে এডেন স্পেস আর সারভাইভর স্পেসের সাইজের অনুপাত
  • -XX:NewRatio   নির্ধারণ করে ওল্ড জেনারেশন আর ইয়ং জেনারেশনের সাইজের অনুপাত
এছাড়া গারবেজ কালেকটরের ধরন অনুযায়ী বেশ কিছু জেভিএম অপশন রয়েছে, যেগুলো গারবেজ কালেকটর এলগরিদম অংশে আলোচনা করা হয়েছে।

কমান্ড লাইনে রান করার জন্য java কমান্ডের পর আর্গুমেন্টগুলো একটার পর একটা দিয়ে দিলে হবে। যেমনঃ
java -Xms128m -Xmx256m ...
আইডিই যেমন একলিপসে রান করতে চাইলে “Run Configurations” এ গিয়ে “Arguments” ট্যাবে ভিএম আর্গুমেন্ট দিয়ে দিতে হবে:
অ্যাপ্লিকেশান সার্ভার যেমন টমক্যাটের কনফিগারেশনেও জেভিএম আর্গুমেন্ট দেয়া যায়। টমক্যাটের bin ডিরেক্টোরির catalina.sh (উইন্ডোজের ক্ষেত্রে catalina.bat) ফাইলের CATALINA_OPTS অথবা JAVA_OPTS ভেরিয়েবলে আর্গুমেন্টগুলো দিয়ে দিতে হবে। যেমনঃ
CATALINA_OPTS=-Xms128m -Xmx256m
হিপ মেমরি ও জিসি মনিটর করা
হিপ মেমরি আর গারবেজ কালেকশনের কাজকর্ম দেখার জন্য বিভিন্ন রকম টুল ব্যবহার করা যায়। আমরা এখানে কমান্ড লাইন টুল jstat এবং গ্রাফিকাল ইউজার ইনটারফেস টুল VisualVM ও Visual GC কিভাবে ব্যবহার করতে হয় সেটা দেখবো।

১। কমান্ড লাইন টুল jstat দিয়ে
কমান্ড লাইন টুল jstat আলাদাভাবে ইন্সটল করতে হয় না, জেডিকে(JDK)-এর সংগেই থাকে। jstat কমান্ড রান করার জন্য আমাদের জাভা অ্যাপ্লিকেশানের প্রসেস আইডি জানতে হবে। লিনাক্স কিংবা ম্যাকে নিচের কমান্ড দিয়ে প্রসেস আইডি জানতে হবেঃ
ps -ef | grep java
প্রসেস আইডি জানার পর নিচের কমান্ড দিয়ে jstat ব্যবহার করা যাবেঃ
jstat -gc [JAVA_PID] [INTERVAL_MS]
শেষ প্যারামিটার (INTERVAL_MS) দিয়ে আমরা নির্ধারণ করতে পারি কত মিলিসেকেন্ড সময় পর পর আপডেটেড ইনফর্মেশন দেখাবে। jstat কমান্ডের একটা উদাহরণঃ
jstat -gc 1539 1000
উপরের কমান্ড দিয়ে আমরা অনেকটা নিচের মত আউটপুট দেখতে পারিঃ
jstat কমান্ড আউটপুটের কলামগুলোর সংক্ষিপ্ত বর্ণনাঃ
  • S0C    সারভাইভর স্পেস-0 এর বর্তমান ধারণক্ষমতা (কিলোবাইট).
  • S1C    সারভাইভর স্পেস-1 এর বর্তমান ধারণক্ষমতা (কিলোবাইট).
  • S0U    ব্যবহৃত সারভাইভর স্পেস-0 (কিলোবাইট).
  • S1U    ব্যবহৃত সারভাইভর স্পেস-1 (কিলোবাইট).
  • EC    এডেন স্পেসের বর্তমান ধারণক্ষমতা (কিলোবাইট).
  • EU    ব্যবহৃত এডেন স্পেস (কিলোবাইট).
  • OC    ওল্ড জেনারেশন স্পেসের বর্তমান ধারণক্ষমতা (কিলোবাইট).
  • OU    ব্যবহৃত ওল্ড জেনারেশন স্পেস (কিলোবাইট).
  • MC    মেটাস্পেসের ধারণক্ষমতা (কিলোবাইট)
  • MU    ব্যবহৃত মেটাস্পেস (কিলোবাইট)
  • CCSC    কমপ্রেসেড ক্লাস স্পেসের ধারণক্ষমতা (কিলোবাইট)
  • CCSU    ব্যবহৃত কমপ্রেসেড ক্লাস স্পেস (কিলোবাইট)
  • YGC    ইয়ং জেনারেশন গারবেজ কালেকসনের সংখ্যা
  • YGCT    ইয়ং জেনারেশন গারবেজ কালেকসনের সময়
  • FGC    ফুল জিসির সংখ্যা
  • FGCT    ফুল জিসির সময়
  • GCT    সর্বমোট গারবেজ কালেকসনের সময়
২। VisualVM ও Visual GC ব্যবহার করে
হিপ মেমোরি ও গারবেজ কালেকসনের কার্যক্রম যদি আমরা ভিস্যুয়ালি দেখতে চাই বা গ্রাফিক্যাল ইউজার ইন্টারফেস ব্যবহার করে দেখতে চাই, তাহলে VisualVM একাজের জন্য খুব ভালো একটা টুল। এটি জেডিকের (JDK) সাথে বিল্ট-ইন দেয়া থাকে। কমান্ড লাইনে নিচের ছোট কমান্ড দিয়ে VisualVM অ্যাপ্লিকেশান চালু করা যায়:
jvisualvm
এটি চালু হবার পর বাম পাশের অ্যাপ্লিকেশানস (Applications) ট্যাবে জাভা অ্যাপ্লিকেশানগুলোর তালিকা পাওয়া যাবে, যেখান থেকে লোকাল ও রিমোট যেকোনো অ্যাপ্লিকেশান নির্বাচন করা যায়, যা আমরা মনিটর করতে পারি। ডানপাশের মনিটর (Monitor) ট্যাবে সিপিউর (CPU) ব্যবহার, মেমরির ব্যবহারের বিভিন্ন গ্রাফ দেখা যায়। নিচে মনিটর ট্যাবের একটি স্ক্রীনশটঃ

VisualVM-এর একটা দরকারি প্লাগইন হচ্ছে Visual GC। এটা ইন্সটল করার জন্য Tools মেনু থেকে Plugins অপশন সিলেক্ট করতে হবে। Plugins উইনডো থেকে Visual GC ইন্সটল করে নিতে হবে। ইন্সটল হবার পর বামপাশের লিস্ট থেকে অ্যাপ্লিকেশান সিলেক্ট করলে Visual GC নামে আরেকটা ট্যাব থাকবে যেখানে হিপ মেমোরি ও গারবেজ কালেকসনের কিছু গ্রাফ দেখা যাবে। নিচে Visual GC ট্যাবের একটি স্ক্রীনশটঃ

চাইলে কোন রিমোট সার্ভারের মেমরিও আমরা মনিটর করতে পারি। সেক্ষেত্রে JMX connection তৈরি করে আমাদের সংযুক্ত হতে হবে। এক্ষেত্রে অবশ্যই রিমোট সার্ভারের জেভিএম অপশনে jmxremote এর সাথে সম্পর্কিত প্যারামিটারগুলো থাকতে হবে। jmxremote প্যারামিটারগুলোর একটি উদাহরণ নিচে হলঃ
    -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9010 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
কোন কারণে অ্যাপ্লিকেশানে মেমরি লিক হলে বা OutOfMemoryError পাওয়া গেলে হিপ ডাম্প (Heap Dump) বিশ্লেষণ করে এর কারণ খুঁজে বের করা যায়। নিচের জেভিএম অপশন ব্যবহার করলে অ্যাপ্লিকেশানে যদি OutOfMemoryError হয়, তখন একটা হিপ ডাম্প ফাইল তৈরি হবেঃ
-XX:+HeapDumpOnOutOfMemoryError –XX:HeapDumpPath=[file path]
নিচে হিপ ডাম্প ট্যাবের একটি স্ক্রীনশটঃ

গারবেজ কালেকটর এলগরিদমসমূহ
মূলত চার ধরনের গারবেজ কালেকটর আছে যেগুলো ভিন্ন ভিন্ন এলগরিদম ব্যবহার করে। প্রত্যেকটারই কিছু সুবিধা, অসুবিধা আছে। অ্যাপ্লিকেশানের চাহিদা অনুসারে আমাদের বেছে নিতে হবে কোন গারবেজ কালেকটর করাটা বেশি সুবিধাজনক হবে।

১। সিরিয়াল কালেকটর
সিরিয়াল কালেকটরের কাজের পদ্ধতি সবচেয়ে সরল যা সিরিয়ালি কাজ করে বা একক থ্রেড (Single thread) ব্যবহার করে কাজ করে। এটি মার্ক-সুইপ-কমপ্যাক্ট পদ্ধতি প্রয়োগ করে গারবেজ কালেকট করে থাকে। এটি ক্লায়েন্ট মেশিন বা একক-সিপিউ (Single-CPU) মেশিনের জন্য বেশি উপযোগী। যেসব অ্যাপ্লিকেশান ১০০ মেগাবাইটের কম মেমরি ব্যবহার করে, বা খুব বেশি রেস্পন্সিভ হবার দরকার নেই, সেসব অ্যাপ্লিকেশানে সিরিয়াল কালেকটর ব্যবহার করা যায়। -XX:+UseSerialGC জেভিএম অপশন দিয়ে সিরিয়াল কালেকটর নির্বাচন করা যায়।

২। প্যারালাল বা থ্রপুট কালেকটর  
প্যারালাল কালেকটর সিরিয়াল কালেকটরের মত করেই কাজ করে, পার্থক্য হল এটা ইয়ং জেনারেশন কালেকট করার জন্য একাধিক থ্রেড (Multiple thread) ব্যবহার করে। সাধারণভাবে এটা সিস্টেমের সিপিউ কোর (CPU core) সংখ্যার সমান সংখ্যক থ্রেড ব্যবহার করে। অবশ্য –XX:ParallelGCThreads=n জেভিএম অপশন দিয়ে থ্রেডের সংখ্যা নির্ধারণ করে দেয়া যায়। তবে চাইলে ওল্ড জেনারেশনের জন্যেও একাধিক থ্রেড কাজে লাগানো যায়। সেক্ষেত্রে, -XX:+UseParallelOldGC জেভিএম অপশন দিয়ে দিতে হবে। তখন ইয়ং জেনারেশন ও ওল্ড জেনারেশন উভয়ের জন্যই একাধিক থ্রেড ব্যবহার করা হবে। একাধিক সিপিউ কোর ব্যবহার করে থাকে বলে একে থ্রপুট কালেকটরও বলা হয়। সেসব অ্যাপ্লিকেশানে বড় কাজ (এই যেমন ব্যাচ জব প্রসেস করার কাজ) করতে হবে এবং দীর্ঘ বিরতি (long pause) তেমন কোন সমস্যা নয়, সেসবে প্যারালাল কালেকটর ব্যবহার করা যায়।

৩। সিএমএস কালেকটর
কনকারেন্ট মার্ক সুইপ (Concurrent Mark Sweep) বা সিএমএস কালেকটর ডিজাইন করা হয়েছে স্বল্প বিরতির (low pause) কালেকটর হিসেবে। মাইনর জিসির সময় এটা সব অ্যাপ্লিকেশান থ্রেড বন্ধ রাখে এবং একাধিক থ্রেড ব্যবহার করে কাজ করে। অর্থাৎ ইয়ং জেনারেশন কালেক্ট করার জন্য এর কাজের পদ্ধতি মোটামুটি প্যারালাল কালেকটরের মতই। ওল্ড জেনারেশনের জন্যে সিএমএস কালেকটর ভিন্ন পদ্ধতিতে কাজ করে। এটা অ্যাপ্লিকেশান থ্রেডসমূহ বন্ধ না করেই কিছু ব্যাকগ্রাউন্ড জিসি থ্রেড দিয়ে ওল্ড জেনারেশন স্ক্যান করতে থাকে এবং অব্যবহৃত অবজেক্টগুলোকে মুছে ফেলতে থাকে। অ্যাপ্লিকেশান থ্রেডসমূহ বন্ধ করা হয় শুধু ইয়ং জেনারেশন কালেক্ট করার জন্য। একারণে বিরতির পরিমাণ অনেক কম হয়। সিএমএস কালেকটর নির্বাচন করা যায় -XX:+UseConcMarkSweepGC জেভিএম অপশন দিয়ে এবং ব্যাকগ্রাউন্ড জিসি থ্রেডের সংখ্যা নির্ধারণ করা যায় -XX:ParallelCMSThreads=n জেভিএম অপশন দিয়ে। যেসব অ্যাপ্লিকেশান খুব রেসপন্সিভ বা স্বল্প বিরতি গ্রহণযোগ্য, সেসবে সিএমএস কালেকটর ব্যবহার করা যায়। সিএমএস কালেকটরের কিছু সীমাবদ্ধতা রয়েছে। অ্যাপ্লিকেশান থ্রেডের সংগে একসাথে চলমান ব্যাকগ্রাউন্ড জিসি থ্রেডগুলোর হিপ স্ক্যান করার কাজ করার জন্য পর্যাপ্ত পরিমাণ সিপিউ সাইকেল (CPU cycles) সিস্টেমে থাকতে হবে। আর ব্যাকগ্রাউন্ড জিসি থ্রেডগুলো মেমরি কমপ্যাক্ট করার কাজ করেনা। একারণে হিপ মেমোরি ফ্রাগমেন্টেড (fragmented) বা বিক্ষিপ্ত হয়ে যেতে পারে। যখন ব্যাকগ্রাউন্ড জিসি থ্রেডগুলো পর্যাপ্ত পরিমাণ সিপিউ সাইকেল না পায়, অথবা হিপ মেমোরি অনেক বেশি ফ্র্যাগমেন্টেড হয়ে যায়, তখন অ্যাপ্লিকেশান থ্রেডসমূহ বন্ধ করে একটা ফুল জিসি সম্পন্ন করা হয়। এইক্ষেত্রে বিরতির পরিমাণ বেশি থাকে।

৪। জি১ কালেকটর
জি১ (Garbage first) কালেকটর ডিজাইন করা হয়েছে বড় হিপ মেমরি নিয়ে কাজ করার জন্য এবং একই সাথে স্বল্প বিরতির কালেকটর হিসেবে। এটা হিপ মেমরিকে কিছু সংখ্যক সমান আকারের রিজিয়ন বা অংশে ভাগ করে কাজ করে। এরমধ্যে কয়েকটা রিজিয়ন মিলে ইয়ং জেনারেশন, কয়েকটা রিজিয়ন মিলে সারভাইভার স্পেস ও কয়েকটা রিজিইয়ন মিলে ওল্ড জেনারেশন গঠিত হয়।
জি১ কালেকটর হিপ
অন্যান্য কালেক্টরের মত সকল অ্যাপ্লিকেশান থ্রেড বন্ধ ইয়ং জেনারেশনে গারবেজ কালেক্ট করা হয়। জি১ এক প্রকার কনকারেন্ট কালেকটরও কারণ অ্যাপ্লিকেশান থ্রেডসমূহ বন্ধ না করে কিছু ব্যাকগ্রাউন্ড জিসি থ্রেড দিয়ে এটা ওল্ড জেনারেশন কালেক্ট করতে থাকে। জি১ কালেকটর ওল্ড জেনারেশনের অবজেক্টগুলো ক্লিন করার জন্য এক রিজিয়ন থেকে আরেক রিজিয়নে কপি করে। এসময় জি১ কালেকটর কমপ্যাক্ট করার কাজও করে থাকে। তাই জি১ কালেকটর ব্যবহার করলে হিপ মেমরি ফ্রাগমেন্টেড হবার সম্ভাবনা অনেক কম থাকে। -XX:+UseG1GC জেভিএম অপশন দিয়ে জি১ কালেকটর নির্বাচন করা যায়। যেসব রেসপন্সিভ অ্যাপ্লিকেশানের হিপ মেমরি সাইজ বেশি (৪ জিবির বেশি), সেসবে জি১ কালেকটর ব্যবহার করা ভালো।
সিএমএস কালেকটরের মত জি১ কালেকটরেও ব্যাকগ্রাউন্ড জিসি থ্রেডগুলোর কাজ করার জন্য পর্যাপ্ত পরিমাণ সিপিউ সাইকেল (CPU cycles) সিস্টেমে থাকতে হবে।

জিসি টিউন করা
জিসি টিউন করার জন্য কোন ধরাবাঁধা নিয়ম নেই। গারবেজ কালেকশন সম্পন্ন হবার সময় যদি অ্যাপ্লিকেশানের পারফরম্যান্সে প্রভাব ফেলে, তখন জিসি টিউন করার চেষ্টা করতে হয়। একটা ফুল জিসি সম্পন্ন হতে যদি ১ থেকে ৩ সেকেন্ডের বেশি সময় লাগে, তখন জিসি টিউন করা জরুরি।
পার্মানেন্ট জেনারেশনের কারণে যদি কখনো OutOfMemoryError হয়ে থাকে, তাহলে পার্মানেন্ট জেনারেশনের সাইজ বাড়ানো যায়। আমরা ইতিমধ্যে জেনেছি যে, -XX:PermSize ও -XX:MaxPermSize এ দুটো জেভিএম অপশন দিয়ে পার্মানেন্ট জেনারেশনের সাইজ নির্ধারণ করা যায়।
আমরা যদি দেখতে পাই যে অনেক বেশি সংখ্যক ফুল জিসি সম্পন্ন হচ্ছে, তাহলে ওল্ড জেনারেশনের সাইজ বাড়িয়ে দিতে পারি। তবে ওল্ড জেনারেশনের সাইজ বড় করলে ফুল জিসির সংখ্যা কমে গেলেও ফুল জিসি সম্পন্ন হবার সময়কাল বেড়ে যাবে। অপরপক্ষে, ওল্ড জেনারেশনের সাইজ কমালে ফুল জিসির সম্পন্ন হবার সময়কাল কমবে, কিন্তু ফুল জিসির সংখ্যা বাড়বে কিংবা OutOfMemoryError তখন বেশি ঘটতে পারে। আমরা ইতিমধ্যে আরও জেনেছি যে -XX:NewRatio জেভিএম অপশন দিয়ে ওল্ড জেনারেশন আর ইয়ং জেনারেশনের সাইজের অনুপাত নির্ধারণ করা যায়। যেমন, NewRatio এর ভ্যালূ ২ মানে হল ওল্ড জেনারেশন ঃ ইয়ং জেনারেশন হবে ২ঃ১। NewRatio এর ভ্যালূ গারবেজ কালেকসন পারফরমান্সে গুরুত্বপূর্ণ ভূমিকা রাখে। আমাদের অ্যাপ্লিকেশানের ধরন অনুযায়ী ওল্ড জেনারেশন ও নিউ জেনারেশন সাইজের অনুপাতের অপটিমাল ভ্যালূ খুঁজে বের করতে হবে।

রেফারেন্স
এই ব্লগটি লিখতে নিচের বই আর আর্টিকেলগুলোর সাহায্য নেয়া হয়েছেঃ