您现在的位置: 主页 > 上位机技术 > JAVA > 了解JAVA classloader(2)
本文所属标签:
为本文创立个标签吧:

了解JAVA classloader(2)

来源:网络整理 网络用户发布,如有版权联系网管删除 2018-07-23 

使用CompilationClassLoader

要使用CCL,必须以特殊方式调用程序。不能直接运行该程序,如:% java Foo arg1 arg2;

应以下列方式运行它:

% java CCLRun Foo arg1 arg2

CCLRun是一个特殊的存根程序,它创建CompilingClassLoader并用它来装入程序的主类,以确保通过CompilingClassLoader来装入整个程序。CCLRun使用JavaReflectionAPI 来调用特定类的主方法并把参数传递给它。有关详细信息,请参阅源代码。

运行示例

源码包括了一组小类,它们演示了工作方式。主程序是Foo类,它创建类Bar的实例。类Bar创建另一个类Baz的实例,它在baz包内,这是为了展示CCL是如何处理子包里的代码。Bar也是通过名称装入的,其名称为Boo,这用来展示它也能与CCL工作。

每个类都声明已被装入并运行。现在用源代码来试一下。编译CCLRun和CompilingClassLoader。确保不要编译其它类(Foo、Bar、Baz和Boo),否则将不会使用CCL,因为这些类已经编译过了。

% java CCLRun Foo arg1 arg2

CCL: Compiling Foo.java...

foo! arg1 arg2

bar! arg1 arg2

baz! arg1 arg2

CCL: Compiling Boo.java...

Boo!

请注意,首先调用编译器,Foo.java管理Bar和baz.Baz。直到Bar通过名称来装入Boo时,被调用它,这时CCL会再次调用编译器来编译它。

CompilingClassLoader.java

以下是CompilingClassLoader.java的源代码

// $Id$

import java.io.*;

/*

A CompilingClassLoader compiles your Java source on-the-fly. It checks

for nonexistent .class files, or .class files that are older than their

corresponding source code.

*/

public class CompilingClassLoader extends ClassLoader

{

// Given a filename, read the entirety of that file from disk

// and return it as a byte array.

private byte[] getBytes( String filename ) throws IOException {

// Find out the length of the file

File file = new File( filename );

long len = file.length();

// Create an array that's just the right size for the file's

// contents

byte raw[] = new byte[(int)len];

// Open the file

FileInputStream fin = new FileInputStream( file );

// Read all of it into the array; if we don't get all,

// then it's an error.

int r = fin.read( raw );

if (r != len)

throw new IOException( "Can't read all, "+r+" != "+len );

// Don't forget to close the file!

fin.close();

// And finally return the file contents as an array

return raw;

}

// Spawn a process to compile the java source code file

// specified in the 'javaFile' parameter. Return a true if

// the compilation worked, false otherwise.

private boolean compile( String javaFile ) throws IOException {

// Let the user know what's going on

System.out.println( "CCL: Compiling "+javaFile+"..." );

// Start up the compiler

Process p = Runtime.getRuntime().exec( "javac "+javaFile );

// Wait for it to finish running

try {

p.waitFor();

} catch( InterruptedException ie ) { System.out.println( ie ); }

// Check the return code, in case of a compilation error

int ret = p.exitValue();

// Tell whether the compilation worked

return ret==0;

}

// The heart of the ClassLoader -- automatically compile

// source as necessary when looking for class files

public Class loadClass( String name, boolean resolve )

throws ClassNotFoundException {

// Our goal is to get a

Class objectClass clas = null;

// First, see if we've already dealt with this one

clas = findLoadedClass( name );

//System.out.println( "findLoadedClass: "+clas );

// Create a pathname from the class name

// E.g. java.lang.Object => java/lang/Object

String fileStub = name.replace( '.', '/' );

// Build objects pointing to the source code (.java) and object

// code (.class)

String javaFilename = fileStub+".java";

String classFilename = fileStub+".class";

File javaFile = new File( javaFilename );

File classFile = new File( classFilename );

//System.out.println( "j "+javaFile.lastModified()+" c "+

// classFile.lastModified() );

// First, see if we want to try compiling. We do if (a) there

// is source code, and either (b0) there is no object code,

// or (b1) there is object code, but it's older than the source

if (javaFile.exists() &&

(!classFile.exists() ||

javaFile.lastModified() > classFile.lastModified())) {

try {

// Try to compile it. If this doesn't work, then

// we must declare failure. (It's not good enough to use

// and already-existing, but out-of-date, classfile)

if (!compile( javaFilename ) || !classFile.exists()) {

throw new ClassNotFoundException( "Compile failed: "+javaFilename );

}

} catch( IOException ie ) {

// Another place where we might come to if we fail

// to compile

throw new ClassNotFoundException( ie.toString() );

}

}

// Let's try to load up the raw bytes, assuming they were

// properly compiled, or didn't need to be compiled

try {

// read the bytes

byte raw[] = getBytes( classFilename );

// try to turn them into a class

clas = defineClass( name, raw, 0, raw.length );

} catch( IOException ie ) {

// This is not a failure! If we reach here, it might

// mean that we are dealing with a class in a library,

// such as java.lang.Object

}

//System.out.println( "defineClass: "+clas );

// Maybe the class is in a library -- try loading

// the normal way

if (clas==null) {

clas = findSystemClass( name );

}

//System.out.println( "findSystemClass: "+clas );

// Resolve the class, if any, but only if the "resolve"/

/ flag is set to true

if (resolve && clas != null)

resolveClass( clas );

// If we still don't have a class, it's an error

if (clas == null)

throw new ClassNotFoundException( name );

// Otherwise, return the class

return clas;

}

}

CCRun.java

以下是CCRun.java的源代码

// $Id$

import java.lang.reflect.*;

/*

CCLRun executes a Java program by loading it through a

CompilingClassLoader.

*/

public class CCLRun

{

static public void main( String args[] ) throws Exception {

// The first argument is the Java program (class) the user

// wants to run

String progClass = args[0];

// And the arguments to that program are just

// arguments 1..n, so separate those out into

// their own array

String progArgs[] = new String[args.length-1];

System.arraycopy( args, 1, progArgs, 0, progArgs.length );

// Create a CompilingClassLoader

CompilingClassLoader ccl = new CompilingClassLoader();

// Load the main class through our CCL

Class clas = ccl.loadClass( progClass );

// Use reflection to call its main() method, and to

// pass the arguments in.

// Get a class representing the type of the main method's argument

Class mainArgType[] = { (new String[0]).getClass() };

// Find the standard main method in the class

Method main = clas.getMethod( "main", mainArgType );

// Create a list containing the arguments -- in this case,

// an array of strings

Object argsArray[] = { progArgs };

// Call the method

main.invoke( null, argsArray );

}

}

Foo.java

以下是Foo.java的源代码

// $Id$

public class Foo

{

static public void main( String args[] ) throws Exception {

System.out.println( "foo! "+args[0]+" "+args[1] );

new Bar( args[0], args[1] );

}

}

Bar.java

以下是Bar.java的源代码

// $Id$

import baz.*;

public class Bar

{

public Bar( String a, String b ) {

System.out.println( "bar! "+a+" "+b );

new Baz( a, b );

try {

Class booClass = Class.forName( "Boo" );

Object boo = booClass.newInstance();

} catch( Exception e ) {

e.printStackTrace();

}

}

}

baz/Baz.java

以下是baz/Baz.java的源代码

// $Id$

package baz;

public class Baz

{

public Baz( String a, String b ) {

System.out.println( "baz! "+a+" "+b );

}

}

Boo.java

以下是Boo.java的源代码

// $Id$

public class Boo

{

public Boo() {

System.out.println( "Boo!" );

}

}



              查看评论 回复



嵌入式交流网主页 > 上位机技术 > JAVA > 了解JAVA classloader(2)
 程序 源代码 以下

"了解JAVA classloader(2)"的相关文章

网站地图

围观()