Shell Scripts That In-Line Java

  • strict warning: Non-static method view::load() should not be called statically in /hermes/walnaweb12a/b57/moo.greydragoncom/nodsw/sites/all/modules/views/views.module on line 906.
  • strict warning: Declaration of views_handler_argument::init() should be compatible with views_handler::init(&$view, $options) in /hermes/walnaweb12a/b57/moo.greydragoncom/nodsw/sites/all/modules/views/handlers/views_handler_argument.inc on line 744.
  • strict warning: Declaration of views_handler_filter::options_validate() should be compatible with views_handler::options_validate($form, &$form_state) in /hermes/walnaweb12a/b57/moo.greydragoncom/nodsw/sites/all/modules/views/handlers/views_handler_filter.inc on line 607.
  • strict warning: Declaration of views_handler_filter::options_submit() should be compatible with views_handler::options_submit($form, &$form_state) in /hermes/walnaweb12a/b57/moo.greydragoncom/nodsw/sites/all/modules/views/handlers/views_handler_filter.inc on line 607.
  • strict warning: Declaration of views_handler_filter_boolean_operator::value_validate() should be compatible with views_handler_filter::value_validate($form, &$form_state) in /hermes/walnaweb12a/b57/moo.greydragoncom/nodsw/sites/all/modules/views/handlers/views_handler_filter_boolean_operator.inc on line 159.
Leeland's picture

Sometimes the simplest things get overlooked. There are many times where I need to do something a little cross system languages. For example dynamically deciding on the right arguments to feed to a Java tool or service JVM. Or when I need to do some undirected graph manipulations of data from PowerShell or bash. There is no reason to not step up to the higher level language to get the job done.

However, a lot of people overlook the idea of in-lining the solution directly into the script. Instead most folks will go off and write some other library of stuff that will have to be distributed with the script for it all to work. Personally I like simple deployments and light requirements. So if I need to step up to a higher level language for some bit of information I in-line it. (Naturally I don't do this for things that need more than a handful of lines of code.)

For example Java JVMs that are 32 bit JVM have a maximum heap size of 4GB (theoretically). However, if the service is going to possibly run in production and would appreciate larger heap sizes why not write the service script to dynamically choose good values based on the available memory AND if the JVM can handle more memory?

There are two ways to do this. Both of these are best served by writing the Java class(es) to NOT have a package specification.

The first way is the cleanest for clear understanding later of what you are doing. This is to put the Java code right into the script, write it out to a file, compile it and use it. Here is a simple example of this:


getJavaBitSize.sh

#!/bin/env bash

cd /var/tmp

if [ ! -f JavaBitSize.class ] ; then
cat >JavaBitSize.java <<EOF
/**
 * Get the JVM data model to know if the system is 32 bit
 * or 64 bit.
 */
public class JavaBitSize {

    public static void main(String[] args) {
        System.out.println("JVM Bit size: " + System.getProperty("sun.arch.data.model"));
    }
}
EOF
javac JavaBitSize.java
fi
java JavaBitSize

Of course this only works if the environment has the Java compiler javac. What about production environments that only have a JRE installed? In this case you include the Java class file in a base64 encoded string. That would look like:


getJavaBitSizeBase64.sh

#!/bin/env bash

cd /var/tmp

if [ ! -f JavaBitSize.class ] ; then
base64 -d -i - >JavaBitSize.class <<EOF
yv66vgAAADIALgoADAAVCQAWABcHABgKAAMAFQgAGQoAAwAaCAAbCgAWABwKAAMAHQoAHgAfBwAg
BwAhAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEABG1haW4BABYoW0xq
YXZhL2xhbmcvU3RyaW5nOylWAQAKU291cmNlRmlsZQEAEEphdmFCaXRTaXplLmphdmEMAA0ADgcA
IgwAIwAkAQAXamF2YS9sYW5nL1N0cmluZ0J1aWxkZXIBAA5KVk0gQml0IHNpemU6IAwAJQAmAQAT
c3VuLmFyY2guZGF0YS5tb2RlbAwAJwAoDAApACoHACsMACwALQEAC0phdmFCaXRTaXplAQAQamF2
YS9sYW5nL09iamVjdAEAEGphdmEvbGFuZy9TeXN0ZW0BAANvdXQBABVMamF2YS9pby9QcmludFN0
cmVhbTsBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVp
bGRlcjsBAAtnZXRQcm9wZXJ0eQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJp
bmc7AQAIdG9TdHJpbmcBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwEAE2phdmEvaW8vUHJpbnRTdHJl
YW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWACEACwAMAAAAAAACAAEADQAOAAEA
DwAAAB0AAQABAAAABSq3AAGxAAAAAQAQAAAABgABAAAABQAJABEAEgABAA8AAAA6AAMAAQAAAB6y
AAK7AANZtwAEEgW2AAYSB7gACLYABrYACbYACrEAAAABABAAAAAKAAIAAAAIAB0ACQABABMAAAAC
ABQ=
EOF
fi
java JavaBitSize

BTW, this trick works in PowerShell for C# Objects using the Add-Type cmdlet. Here is how I determine if I am running in a 64 bit or 32 bit process space on Windows using PowerShell and C#:


BitSize.ps1

try
{
Add-Type @'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

public class BitSize
{
	public BitSize() {
	}
	
    [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
    public extern static IntPtr LoadLibrary(string libraryName);

    [DllImport("kernel32", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
    public extern static IntPtr GetProcAddress(IntPtr hwnd, string procedureName);

    private delegate bool IsWow64ProcessDelegate([In] IntPtr handle, [Out] out bool isWow64Process);

    public bool IsOS64Bit()
    {
        return (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor()))
    }

    private static IsWow64ProcessDelegate GetIsWow64ProcessDelegate()
    {
        IntPtr handle = LoadLibrary("kernel32");

        if ( handle != IntPtr.Zero)
        {
            IntPtr fnPtr = GetProcAddress(handle, "IsWow64Process");

            if (fnPtr != IntPtr.Zero)
            {
                return (IsWow64ProcessDelegate)Marshal.GetDelegateForFunctionPointer((IntPtr)fnPtr, typeof(IsWow64ProcessDelegate));
            }
        }

        return null;
    }

    private static bool Is32BitProcessOn64BitProcessor()
    {
      IsWow64ProcessDelegate fnDelegate = GetIsWow64ProcessDelegate();

      if (fnDelegate == null)
      {
        return false;
      }

      bool isWow64;
      bool retVal = fnDelegate.Invoke(Process.GetCurrentProcess().Handle, out isWow64);

      if (retVal == false)
      {
        return false;
      }

      return isWow64;
    }
}
'@
}
catch
{
	$message = $Error[0].Exception.Message
	if ( "Cannot add type. The type name 'BitSize' already exists.".CompareTo($message) -ne 0) {
		throw $Error[0]
	}
}
$bit = New-Object BitSize
if ($bit.IsOS64Bit) {
    "Bit size: 64"
} else {
    "Bit size: 32"
}

This technique can really solve some neat problems.

Enjoy!

Thread Slivers eBook at Amazon