Saturday, May 23, 2015

Java Object Memory Layout/Anatomy [Deep Size of an Object]

Even to the mind of the most experienced Java Developer, the way JVM organises or allocates memory for an Object may not come intuitively. This also includes activities like measuring the size of an Object.

When we use 'new' to instantiate an Object, there is much more data size allocated than is required to just hold the value. For example, if you choose to create java.lang.Integer, the actual int value will be only 1:4 parts of the Object. The remaining is used to hold the metadata - The metadata includes the following:

1. Class: A pointer to the type of the class. In our case, a pointer to the java.lang.Integer class.
2. Flags: A collection of flags that describe the state of the Object, including the hash code of the Object and the shape of the Object (If it is an Array or not)
3. Lock: The synchronization information of the Object, including if it is synchronized currently.

The Object metadata is followed by the actual Object data. In this specific case, an int value.

Example layout of a java.lang.Integer object for a 32-bit Java process

Example layout of a java.lang.Integer object for a 32-bit Java process

[Reference: http://www.ibm.com/developerworks/library/j-codetoheap/]


I tried to explore all possibilities to measure the Object Memory usage as per the above understanding of the Object Allocation. There are many tools, blogs and write-ups on the internet, but all of them provide approximation, which may not be reliably usable. Also, the values which may be returned by each of these will not concur across these tools. 

The only tool that I came across that seems to be reliable and has the source code public is the Java Agent for Memory Measurements [https://github.com/jbellis/jamm]. The author also seems to be the committer for the Cassandra project, and it is being used in Cassandra - Hence, it is a safe bet and should be close to as exact as possible. I went through the source and the logic seems to concur with the memory layout above, Also, since it is being used in very important (and widely used) projects, [i skipped trying it out myself]. In all, this should be your safest [reliablity and performance] bet if you want to use it to introduce custom cache measurements, custom object profiling, server profiling or simply memory profiling tools.

[I plan to write my own tool to measure Object Sizes in Java as reliably as possible - using the above understanding of Java Memory Allocation . Keep checking this Blog to Download the Source and Binary]
 
 

Wednesday, May 20, 2015

Acceptance/Integration Testing in JEE using Arquillian

In Agile Projects using Java/JEE, the focus and scope of the Developer Testing is usually diminished to either Unit Testing or very basic Functional Testing. Arquillian brings in a newer thought process of Integration and Acceptance Testing, which includes Continuous Integration and Testing even within the JEE Container. Especially for JEE Products or Solutions that require functionalities to be Tested across various Containers - this provides the most Productive way. According to the Internet, Arquillian was also the "Duke's Choice Award for Developer Productivity at JavaOne Conference 2011". In my experience, it not only enhances productivity of the Developers but also promotes Good Practices.

It allows you to convert your TestNG or JUnit (Among Others) Test Cases into Arquillian Test Cases with few changes. Also, it allows you to directly use CDI in your test code. This allows you to inject dependencies such as EJB or Web Services directly in your test cases. The central thought process involved in using Arquillian is the ShrinkWrap API provided by it. It allows you to package your product/project code into Archives like JAR, WAR and EAR. Along with the project code that is to be tested, the test cases are also packaged. It then allows multiple Maven Configurations to allow direct deployment into one of these modes (that we used for our product):

1. Outside Container
By allowing Weld-EE container Arquillian Maven Profile, we are in effect allowing an 'Outside Container' testing environment. This should be helpful in Large, Unwieldy projects or products to get over a 'Saturation or Complexity Point' in Logic or Functionality Development. There are a few limitations of this profile, that the developer may not be able to inject container resources like Managed Thread Factories, Data Sources or Cache Containers. The Developer can go building all the logic, functionality and do both the Unit Testing/Integration Testing with other components of the product - until the time there is a need to inject resources that are not provided by this profile. The guideline for usage of this profile should ideally be the very 'initial' development phase of a sprint story.

2. Remote Container (Managed Container)
By allowing either of these Arquillian Maven Profiles, we are in effect allowing an 'Inside the Container' testing environment. Once we are over the initial phase of a sprint story, the Continuous Integration cycle should now involve Integration Testing with other product components on a daily basis. This also includes changing requirements and possibly Regression during the Sprint Cycle. Also, there is a need to start testing with all container resources available. This should be the possible point, that you either start using the Remote or the Managed Container. The ShrinkWrap allows you to directly connect to local or remote host servers to deploy the created or testable Archive. This is done by providing an Arquillian Configuration File. It supports a variety of JEE Container Profiles - Wildfly, JBoss, Glassfish, Websphere, Weblogic and Tomcat (Among Others). By allowing Continuous Integration Testing with other Components, we catch Integration Defects very early in the cycle. In a way, it matches the punchline of Arquillian - "So you can rule your code. Not the bugs." or "Death to all Bugs!". Also, providing a way of Developer Regression Testing Suite, it allows to go ahead safely with the changes in the Product. It also automatically promotes good practices, by not allowing any thought processes to be lost during the development - and allowing developers to write more test cases - that start testing Regression effectively and allow more Functionality coverage. The guideline for usage of this profile should ideally be the  'middle to end' development of a sprint story.

3. Embedded Container
Now, we are through with the 'initial' and even the 'middle to end' cycle of our Development. But all throughout this, there could be a central or nightly build running at the Product Level. The Embedded Container would be the most suitable in my experience, to automatically start off the Container, deploy the ShrinkWrap and do all the Integration Test (Regression as Well). By doing this on a daily basis - In scheduled Product Builds or Nightly Builds - the Confidence Level on the Product Code increases by a very high magnitude. When testing across containers, it should reduce Developer/Tester effort by appreciable levels. Also, the manual task of actually deploying and testing across containers is not required. The guideline for usage of this profile should ideally be the 'nightly builds' for a sprint.

For all of the above profiles, TestNG or JUnit Test Reports are created - which allows you to understand the outcomes better. Also, in most products, the development cycle that is followed by individual developers on their systems is equivalent to:
Code > Build > Deploy > Test > Fix > Deploy > ... [Code]

With Arquillian, in effect the daily cycle is shortened to:
Code > Fix > ... [Code]


The above caters to Integration Testing and Regression Testing. But once we decide on Arquillian in our Products or Solutions - making it inherent part of the Agile Planning Processes, we should enter into a TDD driven approach for Acceptance Testing as well. The pre-planning, planning process - which includes story identification, estimation and work distribution - could trigger off the initial activity of Identifying Acceptance Tests. These Acceptance Tests should be 'accepted' or 'signed off' by the Architect/Reviewer/Owner. So, in effect, though there can be modifications/additions/subtractions - the Acceptance Test should start becoming the final 'sign off' for the successful delivery of the Sprint Story. With Arquillian, this ATDD approach - can be easily implemented or automated. The actual Implementation of these Acceptance Tests will happen during the Sprint Cycle. The Sprint Deliverable that is now available to the Testing Team of a Product for the next Sprint - is bound to have one very initial but even more thorough level of Functionality Testing complete by the Developers. With Acceptance (and Integration) Testing Reports made Available through Arquillian, the Testers' time is now saved and they will be able to Concentrate on Identifying Diverse, Granular or simply more Thought out Test Cases  - In all, increasing Product Quality.

The Salient Features of Arquillian, then, are:
1. Real Tests Inside the JEE Container
2. IDE/Eclipse Friendly Integration Test Cases
3. Test Enrichment/Allowing CDI Directly in Test
4. Classpath Control/Isolation - No Environment Bugs!
5. Debug Directly on the Server/JEE Container
6. Container Agnostic/Various JEE Containers Supported
7. Extensible Platform/Support Frameworks like JUnit/TestNG
8. Integration Tests from Maven Builds inside Container


There are other innovations as well in the Arquillian Project - which I have not evaluated - Arquillian Drone and Arquilllian Graphene (As Also JBoss Forge). The first two can be used in Conjunction with Selenium for more Efficient User Interface Testing - This includes integrating with the Web Driver and also generating Graphical Reports or Screenshots during the Automated Testing Process. Also, JBoss Forge allows to generate boilerplate code or configuration using a Command-Line Tool. That is all I know! :-)


[I am working on a Leading Client Automation Product - Java/JEE - The above guidelines are based on my Evaluation of Arquillian for this fairly Large and Complex Product that is actually Installed on a Desktop OS/Server OS. We require the use of only JEE Container - Wildfly. These facts are based on Arquillian 1.1.7, Wildfly 8.0, Java SE 7 and Java EE 6]
 

Tuesday, May 12, 2015

Java SE 8... What's New? (Part 04/04)

I have provided some of the most important core language enhancements for JDK 8.0, along with code samples. The examples provided below can be directly pasted into your IDE and you may name the class as provided.



Lambda Expressions
Lambda Expression provide a newer way to refer to anonymous methods. It is more like a method interface providing the parameters accepted along with a method body. In a way, it solves the vertical problem - which leads to more maintainable code or lesser lines of code to achieve the same functionality.
 public class jdk8_LambdaExpressions {  
      public static void main(String[] args) {  
           Runnable r2 = () -> System.out.println("Son of God");  
           r2.run(); // note that this is not starting a thread  
      }  
 }  


Parallel Array Operations
Another powerful feature of JDK8 is that parallel operations are allowed on the same set of data. This is by creating stream out of the data. It is guaranteed to be faster if you have multiple processor cores on your system.
 import java.util.ArrayList;  
 import java.util.List;  
 import java.util.Random;  
 public class jdk8_ParallelArrayOperations {  
      static List<Project> projects = new ArrayList<Project>();  
      public static void main(String[] args) {  
           Project project = new Project();  
           project.setName("development");  
           projects.add(project);  
           project = new Project();  
           project.setName("testing");  
           projects.add(project);  
           project = new Project();  
           project.setName("build");  
           projects.add(project);  
           projects.stream().parallel().forEach(a->action(a));  
           for(Project p: projects) {  
                System.out.println(p.getName()+":"+p.getManager());  
           }  
      }  
      public static void action(Project x) {            
           int pmR=new Random().nextInt(1000);  
           x.setManager("john"+pmR);  
      }  
 }  

 class Project {  
      String name;  
      String manager;  
      public String getName() {  
           return name;  
      }  
      public void setName(String name) {  
           this.name = name;  
      }  
      public String getManager() {  
           return manager;  
      }  
      public void setManager(String manager) {  
           this.manager = manager;  
      }  
 }  


Method Parameter Reflection
Another nice feature, particularly useful when you are using Reflection and Debugging large amount of code - You would want additional introspection on the real parameter names. By compiling the code with JDK8 using the following command, we enable this feature. Note that it will lead to use of additional memory/bytecode size.
 javac -parameters jdk8_MethodParameterReflection.java   

The following method illustrates the use of Method Parameter Reflection in a Java Program.
 import java.lang.reflect.Method;  
 import java.lang.reflect.Parameter;  

 public class jdk8_MethodParameterReflection {  
      public static void main(String[] args) {            
           Class<BlackHat> clazz = BlackHat.class;  
           for(Method m: clazz.getDeclaredMethods()) {  
                for(Parameter p: m.getParameters()) {  
                     System.out.println(p.getName());  
                }  
           }  
      }  
 }  
 class BlackHat {       
      public void payload(String hostName, int hostPort, boolean howdy) {            
           System.out.println("i can do something");  
      }  
 }  


Repeating Annotations
Prior to JDK8, there was no easy way to manage repeating annotations, other than the user or the developer providing custom ways to handle them. With JDK8, one is allowed to define the same annotation more than once. You may place the following code under the package 'jdk8.features'.
 package jdk8.features;  
 import java.lang.annotation.Repeatable;  
 import java.lang.annotation.Retention;  
 import java.lang.annotation.RetentionPolicy;  
 @Retention( RetentionPolicy.RUNTIME )  
 @Repeatable(value = jdk8_RepeatableAnnotationsSources.class)  
 public @interface jdk8_RepeatableAnnotationsSource {  
      String version() default "";       
 }  

Now, you can define the Annotation that you had mentioned
as the value for the '@Repeatable' Annotation. You may place the following code under the package 'jdk8.features'.
 package jdk8.features;  
 import java.lang.annotation.Retention;  
 import java.lang.annotation.RetentionPolicy;  
 @Retention(RetentionPolicy.RUNTIME)  
 public @interface jdk8_RepeatableAnnotationsSources {  
      jdk8_RepeatableAnnotationsSource[] value();  
 }  

You can use Repeatable Annotations as follows. Also, you can use any of the methods getAnnotation() or getAnnotationsByType() to parse the annotation and process them.
 import jdk8.features.jdk8_RepeatableAnnotationsSource;  
 import jdk8.features.jdk8_RepeatableAnnotationsSources;  

 @jdk8_RepeatableAnnotationsSource(version = "jdk5")  
 @jdk8_RepeatableAnnotationsSource(version = "jdk6")  
 @jdk8_RepeatableAnnotationsSource(version = "jdk7")  
 public class jdk8_RepeatableAnnotations {  
      public static void main(String[] args) {  
           Class<jdk8_RepeatableAnnotations> clazz = jdk8_RepeatableAnnotations.class;  
           jdk8_RepeatableAnnotationsSources sources1 = clazz.  
                     getAnnotation(jdk8_RepeatableAnnotationsSources.class);            
           jdk8_RepeatableAnnotationsSource[] sources2 = clazz.  
                     getAnnotationsByType(jdk8_RepeatableAnnotationsSource.class);  
           for(jdk8_RepeatableAnnotationsSource source: sources1.value()) {  
                System.out.println(source.version());  
           }  
           for(jdk8_RepeatableAnnotationsSource source: sources2) {  
                System.out.println(source.version());  
           }  
      }  
 }  


Method References

Method References are like Lambda Expressions, except that they allow to specify or refer to the existing method by name. The operator to refer to an existing method name is :: You may place the following code under the package 'jdk8.features'.
 package jdk8.features;  
 public class jdk8_MethodReferencesVO {  
      Integer age;  
      String name;  
      public Integer getAge() {  
           return age;  
      }  
      public void setAge(Integer age) {  
           this.age = age;  
      }  
      public String getName() {  
           return name;  
      }  
      public void setName(String name) {  
           this.name = name;  
      }  
 }  

Note the usage below of Method References. There can be four types of references to methods, including:
  •     Reference to a static method [ContainingClass::staticMethodName]
  •     Reference to an instance method [containingObject::instanceMethodName]
  •     Reference to a constructor [ClassName::new]
  •     Reference to an instance method [ContainingType::methodName {Arbitary Object}]
 import java.util.Arrays;  
 import jdk8.features.jdk8_MethodReferencesVO;  

 public class jdk8_MethodReferences {  
   public int compareByName(jdk8_MethodReferencesVO a, jdk8_MethodReferencesVO b) {  
     return a.getName().compareTo(b.getName());  
   } 
 
   public int compareByAge(jdk8_MethodReferencesVO a, jdk8_MethodReferencesVO b) {  
     return a.getAge().compareTo(b.getAge());  
   }
  
   public static void main(String[] args) {  
           jdk8_MethodReferencesVO[] refs = new jdk8_MethodReferencesVO[5];  
           jdk8_MethodReferencesVO vo1=new jdk8_MethodReferencesVO();  
           vo1.setAge(21);  
           vo1.setName("Frank");  
           refs[0]=vo1;  
           vo1=new jdk8_MethodReferencesVO();  
           vo1.setAge(22);  
           vo1.setName("Ibrahim");  
           refs[1]=vo1;  
           vo1=new jdk8_MethodReferencesVO();  
           vo1.setAge(24);  
           vo1.setName("Vinod");  
           refs[2]=vo1;  
           vo1=new jdk8_MethodReferencesVO();  
           vo1.setAge(19);  
           vo1.setName("Gurdeep");  
           refs[3]=vo1;  
           vo1=new jdk8_MethodReferencesVO();  
           vo1.setAge(25);  
           vo1.setName("Maxovitch");  
           refs[4]=vo1;  
           jdk8_MethodReferences refC = new jdk8_MethodReferences();  
           Arrays.sort(refs, refC::compareByAge);  
           for(jdk8_MethodReferencesVO rvo: refs) {  
                System.out.println(rvo.getAge()+":"+rvo.getName());  
           }  
      }  
 }  


Happy Life with JDK8!

Sunday, May 10, 2015

Java SE 7... What's New? (Part 03/04)

I have provided some of the most important core language enhancements for JDK 7.0, along with code samples. The examples provided below can be directly pasted into your IDE and you may name the class as provided.

Strings in Switch Statement
You may use Strings in your switch statement, which is a powerful tool. The alternative would have been to use a series of if statements with .equals() comparison. You may directly execute the code below in Eclipse to understand better.
 public class jdk7_StringSwitch {  
      static String day = "SAT";  
     
      public static void main(String[] args) {  
           switch(day) {  
                case "MON": { System.out.println("Monday"); break; }  
                case "TUE": { System.out.println("Tuesday"); break; }  
                case "SUN": { System.out.println("Sunday"); break; }  
                case "SAT": { System.out.println("Saturday"); break; }  
           }  
      }  
 }  


Multiple Exception Handling 
Before JDK7, you would have to catch multiple exceptions in a block - with a catch block for each of the thrown checked exception. But sometimes you may want to take actions for many exceptions that are similar or same. Hence, the utility of this feature. You may directly execute the code below in Eclipse to understand better.
 public class jdk7_ExceptionHandling {  
      
      public static void main(String[] args) {  
           try {                 
                Integer value = Integer.parseInt("ABC");  
                File file = new File("exception.txt");  
                FileReader fileReader = new FileReader(file);                 
           } catch(NumberFormatException | FileNotFoundException foe) {  
                System.out.println("Multiple Exception Types");  
           }  
      }  
 }  

 
Try with Resources
You may use/create a resource withing the try block, from JDK7, and use it within the following block. This includes all objects/resources that implement the java.io.Closeable. Automatically on encountering the exception or if there is no exception, the close() method is guaranteed to be called by the runtime.
 public class jdk7_TryWithResources {  
  
      public static void main(String[] args) throws IOException {            
           try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {  
                br.readLine();  
           } finally {  
                System.out.println("All Resources Closed.");  
           }  
      }  
 }  
Make sure that you have a file.txt in your classpath.
 


Diamond Syntax (Type Inference for Generics) 
Sometimes, in application when we are using generics we may end up with a long line of code, that may be very confusing or have poor readability. This is because there may be multiple generic types that are used in the same line. To improve upon this, JDK7 introduces the concept of diamond operator or diamond syntax, where the type of the generic variable is inferred.
 public class jdk7_DiamondSyntax {  
      public static void main(String[] args) {            
           Map<String, Map<String, List<String>>> list = new HashMap<>();  
           List<String> aList = new ArrayList<String>();  
           aList.add("09.10");  
           aList.add("09.20");  
           aList.add("09.22");  
           Map<String,List<String>> iMap = new HashMap<>();  
           iMap.put("radiac", aList);  
           list.put("radia", iMap);  
      }  
 }  


Binary Literals, Underscore in Literals 
Continuing on the aspects of readability for numeric literals, the concept of the underscore is provided to separate numeric literals like at thousands place, millions place, hundredths place, etc. Also, Binary Literals are allowed in JDK7 starting with 0b. All types of numeric literals will allow the use of '_'. You have to make sure that '_' is not used as the (before) first or (after) last digit of the numeric literal AND '_' is not  used adjacent to the decimal point AND '_' is not used before the F or the L suffix.
 public class jdk7_Literals {  
      int million = 100_000_000;  
      byte b = (byte) 0b0001111111;  
      short s = (short) 0b111100000000;   
      int i = 0b11111111111111111111;  
     
      public static void main(String[] args) {  
           
           jdk7_Literals l = new jdk7_Literals();  
           System.out.println(l.million);  
           System.out.println(l.b + ":" + l.s + ":" + l.i);  
      }  
 }  


Happy Times with JDK 7!

Java SE 6... What's New? (Part 02/04)

I have provided some of the most important core language enhancements for JDK 6.0, along with code samples. The examples provided below can be directly pasted into your IDE and you may name the class as provided.
 
Communication Between Sender and Receiver (SOAP Web Services)
 

From JDK6, Java allows the creation, publishing and lookup of web services through a mixture of annotations and command-line utilities. The below is located in package 'jdk6.features'
 package jdk6.features;  
 import javax.jws.WebMethod;  
 import javax.jws.WebService;  
 import javax.xml.ws.Endpoint;  

 /**  
  * @author sumith_puri  
  *  
  * credits: https://weblogs.java.net/blog/vivekp/archive/2006/12/webservices_in.html  
  *   
  * apt -d sample jdk6_WebServices.java  
  * java -cp sample jdk6.features.jdk6_WebServices  
  * wsimport -p client -keep http://localhost:8080/calculator?wsdl  
  */  
 @WebService  
 public class jdk6_WebServices {  
      @WebMethod  
      public int add(int a, int b) {  
           return (a+b);  
      }  
      public static void main(String[] args) {  
           jdk6_WebServices calculator = new jdk6_WebServices();  
           Endpoint endpoint = Endpoint.publish("http://localhost:8080/calculator", calculator);  
      }  
 }  

In the same folder as the root of the above source file/package, you should type the following:
apt -d sample jdk6_WebServices.java  

Then type the following, to deploy the Web Service at the specified URL.
java -cp sample jdk6.features.jdk6_WebServices

Now, it is time to create the client. You may use the following command to create the client stubs.
wsimport -p client -keep http://localhost:8080/calculator?wsdl 

We can import the generated sources from the 'client' folder now to Eclipse. Using the imported client stubs, you can create client application using the following. Execute it either on command-line or from Eclipse (Run As > Java Application)
 package client;  

 public class JDK6WebServicesClientApp {  
      public static void main(String[] args) {          
           Jdk6WebServicesService service = new Jdk6WebServicesService();  
           Jdk6WebServices serviceProxy = service.getJdk6WebServicesPort();  
           int result = serviceProxy.add(12, 12);  
           System.out.println("Sum: " + result);  
      }  
 }  


Java Compiler API
A powerful feature in JDK6 that will be of really help to create artifacts such as plugins, filters, extensions for dynamic (customer based or client based) execution - is Dynamic Compilation using the Java Compiler API.
 public class jdk6_DynamicCompilation {  

      public static void main(String[] args) throws Exception {            
           System.out.println("Testing Dynamic Compilation....");  
           System.out.println("plugin\\Plugin.java");       
           String fileToStream = "plugin" + java.io.File.separator + "Plugin.java";  
           JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();                 
           FileOutputStream fileOutputStream = new FileOutputStream("errors.txt");  
           int compilationResult = javaCompiler.run(null, null, fileOutputStream,   
                                                          "-verbose", fileToStream);            
           System.out.println("Compilation Result..." + compilationResult);  
      }  
 }  

The following code should be provided under 'plugin'. You may name it as 'Plugin.java'
 package plugin;  
   
 public class Plugin {  
      public boolean filter(String data) {            
           boolean flag=false;  
           if(data.contains("fish")) {                 
                flag=true;  
           }  
           return flag;  
      }  
 
     public static void main(String[] args) {  
      }  
 }  

You may now run the jdk6_DynamicCompilation and obtain Plugin.class as dynamically compiled class under the 'plugin' folder.  Now execute the generated class either using reflection (which you may use in real-world products or solutions) or from the command-line.
java -cp . plugin.Plugin


Scripting Language Support
With JDK6, you may execute JavaScript (Tcl, Ruby, Groovy, etc.) from within Java. This is possible through ScriptingEngine. The example below shows the usage of JavaScript within Java.

 package jdk6.features;  
 import java.io.File;  
 import java.io.FileReader;  
 import javax.script.Invocable;  
 import javax.script.ScriptEngine;  
 import javax.script.ScriptEngineManager;  
   
 public class jdk6_Scripting {  
      public void todaysLogic() throws Exception {            
        // dynamically change script - invoke code in groovy, js - even tcl!  
        ScriptEngineManager manager = new ScriptEngineManager();  
        ScriptEngine jsEngine = manager.getEngineByName("JavaScript");  
        System.out.println(jsEngine.toString());  
        if (jsEngine instanceof Invocable) {  
             try {  
                  File file = new File("market.js");  
             } catch (Throwable e) {  
                  e.printStackTrace();  
             }              
             FileReader reader = new FileReader("market.js");              
             jsEngine.eval(reader);              
             ((Invocable) jsEngine).invokeFunction("current");  
         }  
      }  
      public static void main(String[] args) throws Exception {  
           jdk6_Scripting scripting = new jdk6_Scripting();  
           scripting.todaysLogic();  
      }  
 }  

You must place the following JavaScript code in your classpath, maybe within the root folder of your Eclipse Project. You should name it 'market.js'
 function current() {  
   var x = "", i;  
   for (i=0; i<100; i++) {  
        x="";  
        x = x + "The Number Is " + i;  
        println(x);  
   }    
 }  


Happy Programming with JDK6!

Java SE 5... What's New? (Part 01/04)

I have provided some of the most important core language enhancements for JDK 5.0, along with code samples. The examples provided below can be directly pasted into your IDE and you may name the class as provided.


Type Safe Enumerations
Enumerations are provided as an easier way to maintain similar values (constants) that can be assigned to a type. The keyword used is enum. You may additionally define constructors. The method ordinal() will return the index of the enum constant and the method name() will return the name of the enum constants. You may also use valueOf() to return the value of a string as an enum constant. You may directly execute the code below in Eclipse to understand better.
 public class jdk5_Enum {  
      public static enum Java {JDK5, JDK6, JDK7, JDK8};  
      public static enum JavaVer {   
           JDK5(5), JDK6(6), JDK7(7), JDK8(8);  
           int x;  
           JavaVer(int x) {  
                this.x = x;  
           }  
      }  
     
      public static void main(String[] args) {  
           Java java = Java.JDK6;  
           System.out.println(Java.JDK5);  
           System.out.println(java);  
           System.out.println(java.ordinal() + ":" + java.name());  
           JavaVer javaVer = JavaVer.JDK7;  
           System.out.println(javaVer.x);  
           System.out.println(javaVer.ordinal() + ":" + javaVer.name());  
           String myJava = "JDK8";  
           System.out.println(Java.valueOf(myJava));  
           JavaVer javaSwitchVer=JavaVer.JDK6;  
           switch(javaSwitchVer) {  
                case JDK5: {System.out.println("5.0"); break;}  
                case JDK6: {System.out.println("6.0"); break;}  
                case JDK7: {System.out.println("7.0"); break;}  
                case JDK8: {System.out.println("8.0"); break;}  
           }  
      }  
 }  


Variable Arguments
Varargs should be provided as the last parameter of any method and can be used to pass zero or more arguments to the method. You may directly execute the code below in Eclipse to understand better.
 public class jdk5_Varargs {  
      public void getData(String...values) {  
           for(String string:values) {  
                System.out.println(string);  
           }  
      }  
     
      public static void main(String[] args) {  
           jdk5_Varargs varargs = new jdk5_Varargs();  
           varargs.getData("Apple","Banana","Cucumber","Radish");       
           String[] vargs = new String[] {"Radia","Cloud","Hewlett","Packard"};  
           varargs.getData(vargs);  
      }  
 }  


Generics
Generics is used to maintain compile-time type safety on code. It follows type erasure and allows to maintain a control over the types that can be maintained in collections. You may also use generics to define method or class 'templates'. You may directly execute the code below in Eclipse to understand better. For more on generics, refer to my article in CodeGuru.
 public class jdk5_Generics {  
      List<String> genericList = new ArrayList<String>();  
   
      public static void main(String[] args) {            
           jdk5_Generics jGenerics = new jdk5_Generics();  
           // generic for type safety  
           List<String> jGenericsList = jGenerics.genericList;  
           jGenericsList.add("Sumith");  
           jGenericsList.add("Kumar");  
           jGenericsList.add("Puri");  
           for(String str:jGenericsList) {  
                System.out.println(str);  
           }  
           // generic variables - class and method generic templates  
           List<? extends Vehicle> jGenericObjList = new ArrayList();  
           Vehicle car = new Car();  
           RentVehicle<Vehicle> rentVehicle = new RentCar<Car>();  
           rentVehicle.rentOut(car);  
      }  
 }  
 class Vehicle {  
      Integer regn;  
      String type;  
      public Integer getRegn() {  
           return regn;  
      }  
      public void setRegn(Integer regn) {  
           this.regn = regn;  
      }  
      public String getType() {  
           return type;  
      }  
      public void setType(String type) {  
           this.type = type;  
      }            
 }  
 class Car extends Vehicle {  
 }  
 interface RentVehicle <T extends Vehicle> {  
      public void rentOut(T vehicle);  
 }  
 class RentCar<Car> implements RentVehicle{  
      public void rentOut(Vehicle vehicle) {            
           System.out.println("Rent Vehicle => Rent Car");  
      }  
 }  


Autoboxing/Unboxing
Autoboxing or Unboxing will allow to convert from primitive types to wrapper types and vice versa. You may directly execute the code below in Eclipse to understand better.
 public class jdk5_Autoboxing {  
      Integer integer = new Integer(50);  
      public void setValue(int integer) {  
      }  
      public Integer getValue() {  
           return integer;  
      }  
      public Float getFloat() {  
           return 6.0f;  
      }  
      /**  
       * @param args  
       */  
      public static void main(String[] args) {            
           jdk5_Autoboxing autoboxing = new jdk5_Autoboxing(); // autounboxing  
           autoboxing.setValue(new Integer(5));  
           int x = autoboxing.getValue();  
           // this is not valid => autounboxing - upcasting - autoboxing  
           // Double y = autoboxing.getFloat();  
      }  
 }  


Enhanced For Loop
Enhanced For Loop allows an easier way to loop through objects of a common super-type. You may directly execute the code below in Eclipse to understand better.
 public class jdk5_EnhancedFor {  
      public static void main(String[] args) {  
           jdk5_EnhancedFor ef = new jdk5_EnhancedFor();  
           List<Animal> animals = new ArrayList();  
           Animal animal = new Animal();  
           animals.add(animal);  
           animal = new Dog();  
           animals.add(animal);  
           animal = new Cat();  
           animals.add(animal);  
           animal = new Dog();  
           animals.add(animal);  
           animal = new Cat();  
           animals.add(animal);  
           animal = new Dog();  
           animals.add(animal);  
           animal = new Animal();  
           animals.add(animal);  
           animal = new Animal();  
           animals.add(animal);  
           for(Animal anim: animals) {  
                anim.print();  
           }  
      }  
 }  
 class Animal {  
      public void print() {  
           System.out.println("Animal");  
      }  
 }  
 class Dog extends Animal {  
      public void print() {  
           System.out.println("Dog");  
      }  
 }  
 class Cat extends Animal {  
      public void print() {  
           System.out.println("Cat");  
      }  
 }  


Static Imports
Static Imports allows you to import static methods and fields from other classes or interfaces, most useful when you to easily refer to static members from other classes without the reference of their class. You may directly execute the code below in Eclipse to understand better. Note that it is a compile-time error to import a type from unnamed or default package. 
 import static jdk5.features.jdk5_StaticImport_Source.product;  
 public class jdk5_StaticImport {  
      public static void main(String[] args) {  
           System.out.println(product);  
      }  
 }  
The source for importing the above is the following class which is located under the package 'jdk5.features'

 package jdk5.features;
 public class jdk5_StaticImport_Source {  
      public static final String product = "radia-cloud";  
      public static final String version = "09.20.0000";  
      public static void setup() {  
           System.out.println("Setting up the Radia Server....");  
      }  
      public static void init() {  
           System.out.println("Initializing the Radia Server....");  
      }  
 }  


Annotations 
Annotations are way of syntactic meta-data to inform and use that it signifies a specific type of functionality that can be processed using reflection. It can also be used to suppress warnings and inform of errors. The source file below is located under the package 'jdk5.features'
 package jdk5.features;  
 import java.lang.annotation.ElementType;  
 import java.lang.annotation.Retention;  
 import java.lang.annotation.RetentionPolicy;  
 import java.lang.annotation.Target;  
 @Retention(RetentionPolicy.RUNTIME)  
 @Target({ElementType.FIELD,ElementType.METHOD})  
 public @interface jdk5_Annotation_Source {  
 }  

The RetentionPolicy as mentioned can be either of Runtime (Retained by VM), Source (Discarded by Compiler) or Class (Not be Retained by VM). The source below is located under the package 'jdk5.features'
 package jdk5.features;  
 public class jdk5_Annotation_Usage {  
      @jdk5_Annotation_Source  
      public String myMessage;  
      public void annotated() {  
           System.out.println(myMessage);  
      }  
 }  

Now, You may directly execute the code below in Eclipse to understand Annotations better. (Default Package)
 import java.lang.reflect.Field;  
 import jdk5.features.jdk5_Annotation_Source;  
 import jdk5.features.jdk5_Annotation_Usage;  
 
 public class jdk5_AnnotationProcessor {  
      public static void main(String[] args) throws Exception {  
           jdk5_Annotation_Usage message = new jdk5_Annotation_Usage();  
           Field[] method = message.getClass().getDeclaredFields();  
           for(Field methd: method) {  
                jdk5_Annotation_Source annos = methd.getAnnotation(jdk5_Annotation_Source.class);                 
                if(annos != null) {  
                     methd.set(message,"Messenger of God!");  
                     // using reflection & annotations we set the value - check if set                  
                     message.annotated();   
                }  
           }  
      }  
 }  


Happy Coding with JDK 5!

Thursday, May 7, 2015

Enforce Size Constraints in Infinispan - Java Instrumentation API!

Infinispan does not provide size constraints out of the box, just like almost all of the other standard caching frameworks. You may use the Java Instrumentation API as follows to enforce cache size constraints for your product or project that uses Infinispan.

1. Introduce Instrumentation API in your code
a. Develop a class that has the following method in it. The VM will automatically insert an implementation of the Instrumentation API - once it encounters this method.
 public class ServerInstrumentation {  
      private Instrumentation instrumentation = null;   
      private static final Logger LOGGER = Logger.getLogger(ServerInstrumentation.class);  
      private static ServerInstrumentation serverInstrumentation;  

      public static void premain(String args, Instrumentation pInstrumentation) {  
           serverInstrumentation = new ServerInstrumentation();  
           serverInstrumentation.instrumentation=pInstrumentation;  
      }  
      public static Instrumentation getInstance() {  
           return serverInstrumentation.instrumentation;  
      }  
}

b. You may choose to add the following EJB (optionally) to make this object available throughout your Java EE application. Re-Implement the methods that you need to use from the Instrumentation API. For example, below we have implemented the sizeOf() which actually internally invokes Instrumentation.getObjectSize().
 @Remote  
 public interface ServerInstrumentationInterface {  
      public long sizeOf(Object toBeSized);  
 }  

 @Singleton  
 @Startup  
 public class ServerInstrumentationEJB implements ServerInstrumentationInterface {  
      private static Instrumentation instrumentation;  
      {  
           ClassLoader classLoader=this.getClass().getClassLoader().getParent();  
           try {  
                Class clazz = classLoader.loadClass(ServerInstrumentation.class.getName());  
                instrumentation=(Instrumentation)clazz.getDeclaredMethod("getInstance").invoke(null);                   
           } catch (Exception e) {  
                System.out.println("FFFFFF");  
           }  
      }  
      public long sizeOf(Object toBeSized) {  
           return instrumentation.getObjectSize(toBeSized);  
      }  
 }  

Package this code as 'agent.jar' with the following contents in MANIFEST.MF
 Premain-Class: ServerInstrumentation  
 Agent-Class: ServerInstrumentation  

c. You should place this in the normal deployment location (standalone\deployments) of Wildfly and also mention it as the -javaagent during server startup.The following contents should be in Wildfly standalone.bat
 "%JAVA%" %JAVA_OPTS% "-javaagent:%JBOSS_HOME%\standalone\deployments\agent.jar" ^  
  "-Dorg.jboss.boot.log.file=%JBOSS_LOG_DIR%\server.log" ^  
  "-Dlogging.configuration=file:%JBOSS_CONFIG_DIR%/logging.properties" ^  
   -jar "%JBOSS_HOME%\jboss-modules.jar" ^  
   -mp "%JBOSS_MODULEPATH%" ^  
    org.jboss.as.standalone ^  
   "-Djboss.home.dir=%JBOSS_HOME%" ^  
    %SERVER_OPTS%  

At the end of this, the Instrumentation methods are available throughout your Java EE application for all instrumentation purposes. The EJB will act as a facade over this functionality. Make sure that the following settings exist in your standalone.conf.bat
set "JAVA_OPTS=%JAVA_OPTS% -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.jboss.logmanager.LogManager -Xbootclasspath/p:d:\wildfly\modules\system\layers\base\org\jboss\log4j\logmanager\main\log4j-jboss-logmanager-1.1.0.Final.jar;d:\wildfly\modules\system\layers\base\org\jboss\logmanager\main\jboss-logmanager-1.5.2.Final.jar" 
set "JAVA_OPTS=%JAVA_OPTS% -Djboss.modules.system.pkgs=org.jboss.byteman,org.jboss.logmanager"


2. Use this in your Actual Application (Client)
a. The lookup code is provided below to perform methods using Instrumentation, such as 'Object Size'. This may be used for multiple purposes in your Java EE products or solutions, apart form caching constraints.
 // let's do the lookup           
ServerInstrumentationInterface cacheInstrumentationService = (ServerInstrumentationInterface)   
               initialContext.lookup("java:global/agent/" + ServerInstrumentationEJB.class.getSimpleName());  
cacheInstrumentationService.sizeOf(new String("Java and Infinispan Caching Innovation")));  

b. The following method can be implemented in a different class (CacheInstrumentation.java) to perform the following function everytime you add an element to the cache, to check whether the Allocated Size is exceeded. This will have the above EJB Reference/Instance encapsulated in it.
 public boolean isEntityCacheLimitExceeded(Cache cache) {  
           boolean exceeded=false;  
           long currSize = cacheInstrumentationService.sizeOf(cache);  
           long allocSize = 10*1000*1024;  // 10 MB = 10 * 1000 * 1024 bytes
           if(currSize >= allocSize) {  
                exceeded=true;  
           }  
           return exceeded;  
}  


3. Use ConfigurationBuilder to Introduce Constraints
a. The following method will be used to setConfiguration() which will help to notify Infinispan that the configuration has changed, so that it can perform eviction dynamically.
 public class CacheManagerUtilities {  
      public static Configuration setConfiguration(int maxNumberofEntries) {  
           return new ConfigurationBuilder().eviction().maxEntries(maxNumberofEntries)  
                     .strategy(EvictionStrategy.valueOf("LIRS")).expiration()  
                     .lifespan(2000)  
                     .wakeUpInterval(500)  
                     .maxIdle(1000).build();  
      }  
 }  


4. Request/Enforce Eviction using EvictionManager [defineConfiguration()]
a. Everytime you put/add an element in your cache, you can use the sizeOf() from the EJB to check if the size constraints are exceeded. If they are, then dyanmically change the configuration to make the max-entries limit to the currently existing max-entries. We will now rely on Infinispan's Eviction Algorithms to kick-in and do its duty.
 public void put(K key, V value) {            
           while (true) {  
                if (!cacheInstrumentation.isEntityCacheLimitExceeded(cache)) {  
                     cache.put(key, value);  
                     break;  
                } else {  
                     // set the configuration to the infinispan cache programmatically  
                     Configuration configuration = CacheManagerUtilities.setConfiguration(cache.size());  
                     cache.getCacheManager().defineConfiguration(cache.getName(), configuration);  
                    
                     // start eviction manually  
                     EvictionManager evictionManager = cache.getAdvancedCache().getEvictionManager();  
                     evictionManager.processEviction();  
                     
                     // set the configuration to the infinispan cache programmatically - large number such as 9999  
                     configuration = CacheManagerUtilities.setConfiguration(9999);  
                     cache.getCacheManager().defineConfiguration(cache.getName(), configuration);  
                }  
           }  
}

The above usually performs three things:
1. Expire all elements that have reached expiration time (Data Container)
2. Expire all elements that have reached expiration time (Cache Store)
2. Remove all elements as per the eviction policy - Prunes to max-entries

You may also test the above using Arquillian to try out whether the eviction works by creating data within test cases that adhere to LIRS, LRU and Size Constraints.


Note that the above code will also make sure that only 'Serializable' objects are allowed to be Cached. Suitable for all Java/Java EE products and solutions that need to Enforce Size as a Constraint mechanism for Caching. Happy Caching!