Burning the Midnight Oil

Research, personal interests, life and all the pretty stuff in between

Archive for the ‘Research’ Category

Starting JADE (Java Agent Dev Framework) via C++ using JNI

leave a comment »


I figured I’d post my solution to this since the questing has been asked around the web but no actual code has been posted. Essentially you want to:

Step 1: Create a static method within your Java class to instantiate a JADE container.
Step 2: Create a native method to retrieve/create the Java Virtual Machine (JVM) for JADE to live in.
Step 3: Create a native method to invoke the static method in the JAR compiled from step 1 using the JVM from step 2.

Step 1

The official JADE book sheds some light on how to create a JADE container within Java. This short function does the trick:

//Java
  public static boolean startJadePlatform()
    {
        try{
        jade.core.Runtime rt = jade.core.Runtime.instance();
        Profile p = new ProfileImpl();
        container = rt.createMainContainer(p);
        
        }catch(Exception ex)
        {
            Logger.getLogger(PlatformMediator.class.getName()).log(Level.SEVERE, null, ex);
        }
        return (container != null);
    }

Step 2

On the C++ side, I decided to separate my code in two functions. My first function simply creates a java virtual machine to work with. I follow the indications from this post for most of the details.

//C++
JavaVM* startJVM()
{
	/***	Finding the jvm.dll	***/
	DWORD retval;
	HKEY jKey;	// fetch jvm.dll path from registry
	if (retval = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\JavaSoft\\Java Runtime Environment"), 0, KEY_READ, &jKey))
	{
		RegCloseKey(jKey);
		//manage exception
	}

	TCHAR versionString[16]; // version no. => 16 chars
	DWORD bufsize = 16 * sizeof(TCHAR);
	if (retval = RegGetValue(jKey, NULL, TEXT("CurrentVersion"), RRF_RT_REG_SZ, NULL, versionString, &bufsize))
	{
		RegCloseKey(jKey);
		//manage exception
	}

	dllpath = new TCHAR[512];
	bufsize = 512 * sizeof(TCHAR);
	retval = RegGetValue(jKey, versionString, TEXT("RuntimeLib"), RRF_RT_REG_SZ, NULL, dllpath, &bufsize);
	RegCloseKey(jKey);
	if (retval)
	{
		delete[] dllpath;
		//manage exception
	}

	/***	Loading the jvm.dll and functions GetCreatedJavaVMs & CreateJavaVM ***/

	HMODULE jniModule = LoadLibraryA(dllpath);

	delete[] dllpath;
	if (jniModule == NULL)
		return NULL;

	typedef int (JNICALL * JNI_CreateJavaVM)(JavaVM** jvm, JNIEnv** env, JavaVMInitArgs* initargs);
	JNI_CreateJavaVM createJavaVM = (JNI_CreateJavaVM)GetProcAddress(jniModule, "JNI_CreateJavaVM");

	/*** Creating the JVM ***/
	JavaVMInitArgs initArgs;

	JavaVMOption* options = new JavaVMOption[4]; 
	options[0].optionString = "-Djava.compiler=NONE";           /* disable JIT */
	options[1].optionString = "-Djava.class.path=C:\\Users\\you\\yourproject\\dist\\yourjar.jar";	
	options[2].optionString = "-Djava.library.path=c:\\yourlibraries";  /* set native library path */
	options[3].optionString = "-verbose:jni";                   /* print JNI-related messages */

	initArgs.version = JNI_VERSION_1_6;
	initArgs.nOptions = 4;
	initArgs.options = options;
	initArgs.ignoreUnrecognized = false;

	JavaVM* jvm;
	JNIEnv* env;

	typedef jint (JNICALL * GetCreatedJavaVMs)(JavaVM**, jsize, jsize*);
	GetCreatedJavaVMs JNI_GetCreatedJavaVMs;

	JNI_GetCreatedJavaVMs = (GetCreatedJavaVMs)GetProcAddress(jniModule, "JNI_GetCreatedJavaVMs");

	int n;
	retval = JNI_GetCreatedJavaVMs(&jvm,1, (jsize*) &n);

	if (retval == JNI_OK)
	{
		if (n == 0)
		{
			retval = createJavaVM(&jvm, &env, &initArgs);	//create new
		}else
		{
			if (n != 1)
			{
				return NULL;
			}
		}
	}
	return jvm;
}

With that done, your C++ method can already be used to create or fetch a JavaVM instance. You must keep the pointer to the JVM as is the only way to access the JNIEnv between calls.

Step 3

Invoking the JAR functionality doesn’t require much effort. I passed the JavaVM as argument, but there are other alternatives.

//C++
int Environment::startPlatform(JavaVM* jvm){

	JNIEnv* env;
	bool mustDetach = false;

	jint retval = jvm->GetEnv((void**)&env, JNI_VERSION_1_6);
	if (retval == JNI_EDETACHED)
	{
		JavaVMAttachArgs args;
		args.version = JNI_VERSION_1_6;
		args.name = NULL;
		args.group = NULL;
		retval = jvm->AttachCurrentThread((void **)&env, &args);
		mustDetach = true; 
	}
	if (retval != JNI_OK)
		throw retval;

	if (retval == JNI_OK)
	{

		static const char* const jvmClassName = "com/namespace/to/class/Platform";

		jclass clazz =  env->FindClass(jvmClassName);
		if (env->ExceptionCheck())
		{
			env->ExceptionOccurred();
			return JNI_ERR;
		}
		if (clazz == NULL){
			return JNI_ERR;
		}

		jmethodID mid = env->GetStaticMethodID(clazz, "startJadePlatform", "()Z");	//determine signature via javap -s
		if (mid == NULL){
			return JNI_ERR;
		}

		BOOL returnedValue = env->CallStaticBooleanMethod(clazz, mid);

		if (mustDetach)
		{
			jvm->DetachCurrentThread();
		}

		if (returnedValue) return JNI_OK;
		return JNI_ERR;
	}

With this in place, you can call both functions sequentially (passing the respective parameters) and the JADE platform will be initiated within the JavaVM. This implementation checks for existing instances of JavaVM, therefore is safe to use between multiple callbacks and different threads. If you need to set up your environment from scratch or have little knowledge of JNI, these references (1, 2) were very handy.

Good luck!

Advertisements

Written by cd

April 29, 2014 at 10:04 am

Posted in C++, Code, Java, Research

Tagged with , , , , , ,

What is a review article and where do I get one?

leave a comment »

Research Bar

Research Bar (Photo credit: Rice-Aron Library)

There is a sea of research publications out there. Might seem overwhelming to start research in a new area or simply catch up with current trends in a particular field. A good starting point are research articles. These are compilations of  works on a specific topic, field or discipline. Relevant and recent articles are preferred and the value added from this type of publications is the structure and comprehensiveness of the materials.

A review article is the perfect place to glance at the state of art of your discipline, find interesting research questions or quickly gather important references such as key publications and authors. Many journals mark these articles, thus making things easier for us users.

If you are looking for scientific publications, you can find review articles with Scopus using the following simple steps:

  1. Type some relevant terms in the search box. Be as specific as possible.
  2. Set document type to “Review”
  3. Add other appropriate filters (dates, disciplines, etc.)
  4. Arrange the results list based on your preferences (No. of citations, date, etc.)
You may need to tune you query up to find the best term combinations. Also, you still need to verify the publication quality and check for similar options in other portals. Finding that key paper is a difficult task, however this sort of publications are extremely useful in giving insight of new or rapidly changing areas.
%d bloggers like this: