Java Programming
Week 5

Dr. Ernest J. Friedman-Hill

ejfried@herzberg.ca.sandia.gov

http://herzberg.ca.sandia.gov/JavaCourse

First Things First

This Week

Class and ClassLoader

Creating Objects From Data

import java.awt.*;

import java.applet.*;

public class ComponentFrame extends Frame

{

public ComponentFrame(String cname)

throws ClassNotFoundException,

IllegalAccessException,

InstantiationException

{

super(cname);

Component c = (Component)

Class.forName(cname).newInstance();

add(c);

pack();

show();

}

 

public static void main(String[] argv)

{

try {

new ComponentFrame(argv[0]);

} catch (Exception e) {

System.out.println("Can't show " +

argv[0]);

e.printStackTrace();

}

}

}

The Reflection API

class Mystery

{

public int doIt(int i) { return ++i;}

}

 

import java.lang.reflect.*;

class SolveMystery

{

public static void main(String[] argv)

throws Exception

{

Class c = Class.forName(argv[0]);

Object o = c.newInstance();

 

Method m =

c.getMethod(argv[1],

new Class[]{ Integer.TYPE });

 

Object result = m.invoke(o,

new Integer[] { new Integer(3) });

System.out.println(result);

}

}

 

% java SolveMystery Mystery doIt

4

%

java.lang.ClassLoader

 

import java.util.Hashtable;

import java.io.*;

 

class BytesLoader extends ClassLoader

{

Hashtable cache = new Hashtable();

 

public synchronized Class

loadClass(String name, boolean resolve)

throws ClassNotFoundException

{

Class c = (Class) cache.get(name);

if (c == null)

{

try { c = Class.forName(name); }

catch (ClassNotFoundException cnfe) {

byte[] b = null;

try {

FileInputStream fis =

new FileInputStream(

name + ".bytes");

b = new byte[fis.available()];

fis.read(b);

fis.close();

} catch (IOException ioe) {}

 

if (b == null)

throw new

ClassNotFoundException(name);

c = defineClass(name, b, 0, b.length);

}

cache.put(name, c);

}

if (resolve)

resolveClass(c);

return c;

}

}

 

 

import java.awt.*;

public class BlueButton extends Button

{

public BlueButton() { setBackground(Color.blue); }

}

 

class LoaderDemo

{

public static void main(String [] argv)

{

try

{

BytesLoader l =

new BytesLoader();

Class c =

l.loadClass(argv[0], true);

Button b =

(Button) c.newInstance();

b.setLabel("OK");

 

Frame f = new Frame();

f.add(b);

f.pack();

f.show();

}

catch (Throwable e)

{

e.printStackTrace();

}

}

}

 

Security and Details

Inside the Virtual Machine

 

public class Sample

{

int addOne(int i)

{

int j = i + 1;

return j;

}

}

 

c:/users/root/> javap -c Sample

public class Sample extends java.lang.Object

{

int addOne(int);

public Sample();

}

Method int addTwo(int)

// push local variable 1

0 iload_1

// push constant "2"

1 iconst_2

// add top two items, leave sum on stack

2 iadd

// pop into local 2

3 istore_2

// push local 2 to stack

4 iload_2

// return integer value

5 ireturn

 

Method Sample()

// local 0 is always "this"

0 aload_0

1 invokespecial #3 <Method java.lang.Object()>

4 return

 

 

Inside the Virtual Machine

 

import java.io.*;

public class Sample2

{

int getInt(Reader r)

{

try

{

BufferedReader br;

if (r instanceof BufferedReader)

br = (BufferedReader) r;

else

br = new BufferedReader(r, 1);

String s = br.readLine();

return Integer.parseInt(s);

}

catch (IOException ioe)

{

return 0;

}

catch (NumberFormatException nfe)

{

return 0;

}

}

}

 

 

Method int getInt(java.io.Reader)

0 aload_1 // get argument

1 instanceof #2 <Class java.io.BufferedReader>

4 ifeq 15 // branch if not equal

7 aload_1 // get argument again

8 checkcast #2 <Class java.io.BufferedReader>

11 astore_2 // save in 'br'

12 goto 25 // jump over 'new' code

15 new #2 <Class java.io.BufferedReader>

18 dup // copy item on stack

19 aload_1 // push arg

20 iconst_1 // push '1'

21 invokespecial #8 <Method

java.io.BufferedReader(java.io.Reader,int)>

24 astore_2 // store into br

25 aload_2 // get br, either way

26 invokevirtual #10 <Method

java.lang.String readLine()>

29 astore_3 // store result in variable

30 aload_3

31 invokestatic #9 <Method int

parseInt(java.lang.String)>

34 ireturn // return

35 pop // clean up stack, handle IOE

36 iconst_0 // return 0

37 ireturn

38 pop // clean up stack, handle NFE

39 iconst_0

40 ireturn

 

Exception table:

from to target type

0 35 35 <Class java.io.IOException>

0 35 38

<Class java.lang.NumberFormatException>

Field Signatures

Z:boolean C:char B:byte S:short

I:int J:long F:float D:double

L<package-component>/<classname>;

[<field-signature>

Method Signatures

(<argfs>[<argfs>]*)<returnfs>

Native Methods

Native Methods

javah -jni Toast.NativeToaster

 

package Toast;

 

class Toaster {

// Interesting stuff omitted!

}

package Toast;

 

public class NativeToaster

extends Toaster {

// Load the C code when Java is loaded

static {

System.loadLibrary("Toast");

}

 

// We'll define these in C

public native int

getTemperature();

 

public native void

setHeatLevel(String heatlevel);

 

// Method for the C code to call

public void displayMessage(String msg) {System.out.println(msg);}

}

 

 

 

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class Toast_NativeToaster */

 

#ifndef _Included_Toast_NativeToaster

#define _Included_Toast_NativeToaster

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class: Toast_NativeToaster

* Method: getTemperature

* Signature: ()I

*/

JNIEXPORT jint JNICALL

Java_Toast_NativeToaster_getTemperature

(JNIEnv *, jobject);

/*

* Class: Toast_NativeToaster

* Method: setHeatLevel

* Signature: (Ljava/lang/String;)V

*/

JNIEXPORT void JNICALL

Java_Toast_NativeToaster_setHeatLevel

(JNIEnv *, jobject, jstring);

 

#ifdef __cplusplus

}

#endif

#endif

 

 

#include "Toast_NativeToaster.h"

#include <conio.h>

#include <string.h>

 

JNIEXPORT jint JNICALL

Java_Toast_NativeToaster_getTemperature (JNIEnv *env, jobject _this)

{

int temp = _inp(123);

return (jint) temp;

}

 

JNIEXPORT void JNICALL

Java_Toast_NativeToaster_setHeatLevel(

JNIEnv *env,

jobject _this,

jstring heatlevel)

{

char setting[32];

int value;

 

// extract the chars from the jstring

const char *str =

env->GetStringUTFChars(heatlevel, 0);

strcpy(setting, str); // keep a copy

env->ReleaseStringUTFChars(heatlevel, str);

 

 

// map strings to hardware-dependent numbers

if (!strcmp(setting, "HIGH"))

value = 255;

else if (!strcmp(setting, "MEDIUM"))

value = 128;

else if (!strcmp(setting, "LOW"))

value = 64;

else {

// invalid setting; throw an exception

jclass exception = env->FindClass(

"java/lang/IllegalArgumentException");

if (exception)

env->ThrowNew(exception,

"Must be HIGH, MEDIUM, or LOW");

return;

}

 

// set the temperature

_outp(123, value);

 

// display the new setting in Java

// first find the method to call

jclass me = env->GetObjectClass(_this);

jmethodID mid =

env->GetMethodID(me, "displayMessage",

"(Ljava/lang/String;)V");

 

if (!mid) {

// java code changed! throw an exception

jclass exception = env-> FindClass(

"java/lang/IncompatibleClassChangeError");

if (exception)

env->ThrowNew(exception,

"Java code newer than native library");

return;

}

 

// create a Java string to display

jstring msg = env->NewStringUTF(setting);

 

// call the method with the argument.

env->CallVoidMethod(_this, mid, msg);

}

 

Native Methods

Native Methods

 

JNI_CreateJavaVM(..., &env, ...);

(load classes with FindClass,

call methods...)

JNI_DestroyJavaVM(...);

Native Methods

A Look Ahead...