Category Archives: JVM - Page 2

Fiddling with the JVM

Java is a very safe language if used in a normal way, however just like the CLR it can be used in an unsafe manor.

The main reason for using Java in a unsafe manor is performance, some unsafe operations are optimised by the JVM itself.

The boot class loader grants enough permissions to access a key undocumented class sun.misc.Unsafe. As I will state, this is an undocumented class and as the name implies it’s unsafe.

This class provides methods that allows you to manipulate objects and the memory of the objects directly.

For example, you could use it to access the object itself, lets look at an example to manipulate a String object.. not nice I hear you say…. and boy are you are so right. The purpose of this example is to demonstrate the power of the JVM if used to the extreme but not to demonstrate how to destroy the JVM.

import sun.misc.Unsafe;
import java.lang.reflect.Field;

//  To Compile: javac BadBoy.java
//  To Run:        java -Xbootclasspath/p:. BadBoy

public class BadBoy
{
  private final static  Unsafe  unsafe  = Unsafe.getUnsafe();
 
  public static void main(String args[]) throws Exception
  {
   // Find the field "count" inside java.lang.String
   Field field = String.class.getDeclaredField("count");

   // Find the memory offset within the field...
   long countOffset = unsafe.objectFieldOffset(field);

   field = String.class.getDeclaredField("offset");
   long offset4Offset  = unsafe.objectFieldOffset(field);

   // Lets read the memory directory...
   Object  object = "Hello World from Java, the ultra safe language... or is it..";

   int length = unsafe.getInt(object, countOffset);
   System.out.println("The original Length is length: " + length);

   System.out.println("1- The 'object' contains : ");
   System.out.println(" -> "+object);
   System.out.println("  hashCode is : " + object.hashCode());

   unsafe.putInt(object, offset4Offset, 17);
   unsafe.putInt(object, countOffset, 32);
   System.out.println("2- The 'object' contains : ");
   System.out.println(" -> "+object);
   System.out.println("  hashCode is : " + object.hashCode());
 }
}

Then, the output of the example on my little macbook is:

stephen-gennards-macbook:blob spg$ java -Xbootclasspath/p:. BadBoy
The original Length is length: 60
1- The 'object' contains :
 -> Hello World from Java, the ultra safe language... or is it..
  hashCode is : 573430574
2- The 'object' contains :
 -> Java, the ultra safe language...
  hashCode is : 573430574

As you can see the String object is changed but the hashCode remains the same. :-)

Even if the above example seems weird to the extreme and it is, I offer you one take home from this blog…

Be very careful what you place on your “bootclasspath!”

Object COBOL/Java default exception handler

While working on some support recently for our compiler (Micro Focus COBOL compiler that is), I became annoyed with the lack of a reasonable error messages/stack trace output from our Java/COBOL Object support.

I have no idea why our default exception handler for Java exceptions just displays a such a simple message with little or no information.

For those who have not seen it, display something similar to:

Exception 65537 not trapped by the class javaexceptionmanager.
Description: "Java exception"
Test error
Hit T to terminate program. Hit any other key to continue.
instantiated - test

Exception 65537 not trapped by the class javaexceptionmanager.
Description: "Java exception"
Test error
Hit T to terminate program. Hit any other key to continue.

Luckily for me and you, we do expose a mechanism for replacing the default exception handler.

Anyway, with very little effort I created a different “default” system exception handler that display this instead:

instantiated - test 1
java.lang.Exception: Test error
        at SimpleClass.TestException(SimpleClass.java:10)

WARNING: JavaException: Test error
instantiated - test 2
java.lang.Exception: Test error
        at SimpleClass.TestException(SimpleClass.java:10)
WARNING: JavaException: Test error

The key difference being that a Java stack trace is included, boy did this help me.

The program below is the code that implements the exception handler. I am sure someone else can take this example and make it much nicer and provide more features but for this blog I will keep it simple.

      $set ooctrl (+p-f) case
       program-id. ExceptionCatcher.
       
       class-control.
             EntryCallback is class          "entrycll"
             JavaExceptionManager is class   "javaexpt"
             ExceptionManager is class       "exptnmgr"
             Javasup is class "javasup"
             .
       
       working-storage section.
       01 wsCallback                   object reference.
       01 wsIterator                   object reference.
       01 theJavaException             object reference.
       local-storage section.
       01 filler pic x.   *> dummy storage item to allow recursion
       linkage section.
       01 lnkException                 object reference.
       01 lnkErrorObject               object reference.
       01 lnkErrorTextCollection       object reference.
       01 lnkErrorNumber               pic x(4) comp-5.
       01 anElement                    object reference.
         procedure division.
      *>---Set up system level Exception handler
             invoke EntryCallback "new" using
                    z"JException"
                    returning wsCallback
             end-invoke

             invoke ExceptionManager "register" using
                    javaexceptionmanager
                    wsCallback
             end-invoke

             invoke EntryCallback "new" using z"DispError"
               returning wsIterator
             end-invoke

             goback.
       
       
         entry "Jexception" using
                  lnkException
                  lnkErrorNumber
                  lnkErrorTextcollection
             .

              invoke javasup "exceptionOccurred"
                   returning theJavaException
              end-invoke

              if theJavaException not equal null
                invoke theJavaException "printStackTrace"
              end-if
           
              invoke lnkErrorTextCollection "do" using wsIterator
              goback.
             .

          entry "DispError" using anElement
            display "WARNING: JavaException: " with no advancing
            invoke anElement "display"
            display " "
            goback.
             .

To use the above code, you just have to first cut-paste to code into a file called ExceptionCatcher.cbl and include this in your project, and then add the directive INITCALL”ExceptionCatcher”, then away you go.

My test programs for the above example are:

     $set ooctrl (+p-f) case
       program-id. jtest.
       
       class-control.
             SimpleClass is class            "$JAVA$SimpleClass"
             .
       
       working-storage section.
       01 theInstance                  object reference.
       local-storage section.
       01 filler pic x.   *> dummy storage to allow the local entry
         procedure division.
      *>---Instantiate the class
             invoke SimpleClass "new" returning theInstance
       
             display "instantiated - test 1"
             invoke theInstance "TestException"

             display "instantiated - test 2"
             invoke theInstance "TestException"
             stop run.

and the Java class itself:

import java.lang.* ;

public class SimpleClass {
  public SimpleClass() { }

  public void TestException() throws Exception {
     throw new Exception ("Test error" );
  }
}

References: Studio Enterprise 6.0 Document for COBOL/Java Interop