??xml version="1.0" encoding="utf-8" standalone="yes"?>
instsrv.exe srvany.exe
q两个文件是MS扚w生的,|上应该能烂下蝲?/p>
首先这两个文g攑ֈ自定的\径中。例如放在C:\根目录下
在CMD对话框中输入 c:\instsrv.exe servername c:\ srvany.exe 回R
其中servername是你所需要的服务名?/p>
之后你需要进入注册表q行相应的设|,在注册表的:(x)
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\servername
中简历Parameters子项Q然后在其中建立一个字W串ApplicationQ双击该字符Ԍ输入如下格式的语句:(x)
C:\ABC\DEF\XXX.exe +Xms256M +Xmx256M -nodbcheck -minspan60 -retry1000
其中?56M与服务占用内存大有养Iq就要看机器的配|了?/p>
修改l束后推出,使用命o(h)services.mscq入服务界面Q找C刚刚定制的服务,双击q入Q之后选择“登陆”Q再选中“本地登陆”q确定。之后手动启动服务即可?br />
C:\service\instsrv.exe adslSrv "C:\service\srvany.exe"
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" <script type="text/javascript"> function createXMLHttpRequest() { function readRSS(url) { function ResultSet() { } </script> <body"> |
HTTP/1.1 302 Found
Location: http://www.google.com/intl/zh-CN/
Set-Cookie: PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.google.com
Content-Type: text/html
<form name="testform" action="/xxx">
<input type="text">
</form>
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
<session-info>
<path>/NASApp</path>
</session-info>
context.setAttribute("appA", session);
contextA = context.getContext("/appA");
HttpSession sessionA = (HttpSession)contextA.getAttribute("appA");
首先我们定义一个接口,使所有承它的类都必d现actionҎ(gu)Q如下:(x)
public interface ActionInterface {
public String action();
}
完成后将其打包ؓ(f)testInterface.jar文g?/p>
接下来新Z工程Qؓ(f)了编译通过Q引入之前打好的testInterface.jar包。ƈ创徏TestActionc,使它实现ActionInterface接口。如下:(x)
public class TestAction implements ActionInterface {
public String action() {
return " com.mxjava.TestAction.action " ;
}
}
完成后将其打包ؓ(f)test.jarQ放在c盘根目录下。下面要做的是利用URLClassLoader加蝲q运行TestAction的actionҎ(gu)Qƈ返回的值打印在控制C?/p>
新徏一工程Q引入testInterface.jar包。ƈ创徏一可执行类QmainҎ(gu)Q,在其中加入如下代码:(x)
URL url = new URL(“file:C: / test.jar”);
URLClassLoader myClassLoader = new URLClassLoader( new URL[] { url } );
Class myClass = myClassLoader.loadClass(“com.mxjava.TestAction”);
ActionInterface action = (ActionInterface)myClass.newInstance();
System.out.println(action.action());
在上面的例子中,首先利用URLClassLoader加蝲了C:\test.jar包,其中的com.mxjava.TestActionc蝲入内存,其强制转型为testInterface包中的ActionInterfacecdQ最后调用其actionҎ(gu)Qƈ打印到控制台中?/p>
执行E序后,在控制台上如期打印出我们惌的内宏V但是,事情q没有那么简单,当我们将该代码移动web应用中时Q就?x)抛出异常。原来,Java为我们提供了三种可选择的ClassLoaderQ?br />
1. pȝcd载器或叫作应用类加蝲?(system classloader or application classloader)
2. 当前cd载器
3. 当前U程cd载器
在上例中我们使用javac命o(h)来运行该E序Q这时候用的是系l类加蝲?(system classloader)。这个类加蝲器处?-classpath下的cd载工作,可以通过ClassLoader.getSystemClassLoader()Ҏ(gu)调用?ClassLoader 下所有的 getSystemXXX()的静态方法都是通过q个Ҏ(gu)定义的。在代码中,应该量地调用q个Ҏ(gu)Q以其它的类加蝲器作Z理。否则代码将只能工作在简单的命o(h)行应用中。当在web应用中时Q服务器也是利用ClassLoader来加载class的,׃ClassLoader的不同,所以在强制转型时JVM认定不是同一cd。(在JAVA中,一个类用其完全匚wcd(fully qualified class name)作ؓ(f)标识Q这里指的完全匹配类名包括包名和cd。但在JVM中一个类用其全名和一个加载类ClassLoader的实例作为唯一标识。因此,如果一个名为Pg的包中,有一个名为Cl的类Q被cd载器KlassLoader的一个实例kl1加蝲QCl的实例,即C1.class在JVM中表CZؓ(f)(Cl, Pg, kl1)。这意味着两个cd载器的实?Cl, Pg, kl1) ?(Cl, Pg, kl2)是不同的Q被它们所加蝲的类也因此完全不同,互不兼容的。)Z能够使程序正运行,我们首要解决的问题就是,如何URLClassLoader加蝲的类Q同当前ClassLoader保持在同一cd载器中。解x法很单,利用java提供的第三种ClassLoader—当前线E类加蝲器即可。jdk api文档׃(x)发现QURLClassLoader提供了三U构造方式:(x)
// 使用默认的委托父 ClassLoader 为指定的 URL 构造一个新 URLClassLoader?nbsp;
URLClassLoader(URL[] urls)
// 为给定的 URL 构造新 URLClassLoader?nbsp;
URLClassLoader(URL[] urls, ClassLoader parent)
// 为指定的 URL、父cd载器?URLStreamHandlerFactory 创徏?URLClassLoader?
URLClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory)
接下来要做的是Q在构造URLClassLoaderӞ当前线E类加蝲器置入即可。如下:(x)
URLClassLoader myClassLoader = new URLClassLoader( new URL[] { url } , Thread.currentThread().getContextClassLoader());
ȝQ?br />
Java是利用ClassLoader来加载类到内存的QClassLoader本n是用java语言写的Q所以我们可以扩展自qClassLoader。利用URLClassLoader可以加蝲指定jar包中的类到内存。在命行上利用URLClassLoader加蝲jarӞ是用系l类加蝲器来加蝲class的,所以在web环境下,׃(x)出错。这是因为JVM中一个类用其全名和一个加载类ClassLoader的实例作为唯一标识的。我们只要利用URLClassLoader的第二种构造方法ƈ传入当前U程cd载器卛_解决?/p>
在流行的商业化编E语a中,Java 语言׃?Java 虚拟?(JVM) 上运行而显得与众不同。这意味着已编译的E序是一U特D的、独立于q_的格式,q依赖于它们所q行的机器。在很大E度上,q种格式不同于传l的可执行程序格式?
?C ?C++ ~写的程序不同,Java E序q不是一个可执行文gQ而是p多独立的cL件组成,每一个文件对应于一?Java cR?
此外Q这些类文gq立即全部都装入内存,而是Ҏ(gu)E序需要装入内存。ClassLoader ?JVM 中将c装入内存的那部分?
而且QJava ClassLoader 是?Java 语言~写的。这意味着创徏(zhn)自q ClassLoader 非常Ҏ(gu)Q不必了?JVM 的微细节?
如果 JVM 已经有一?ClassLoaderQ那么ؓ(f)什么还要编写另一个呢Q问得好。缺省的 ClassLoader 只知道如何从本地文gpȝ装入cL件。不q这只适合于常规情况,卛_全部~译?Java E序Qƈ且计机处于{待状态?
?Java 语言最h意的事就?JVM 可以非常Ҏ(gu)C那些非本地硬盘或从网l上获取cR例如,览者可以用定制的 ClassLoader ?Web 站点装入可执行内宏V?
有许多其它方式可以获取类文g。除了简单地从本地或|络装入文g以外Q可以用定制的 ClassLoader 完成以下dQ?
定制 ClassLoader CZ
如果使用q?JDK 或Q何基?Java 览器中?Applet 查看器,那么(zhn)差不多肯定使用q定制的 ClassLoader? Sun 最初发?Java 语言Ӟ其中最令h兴奋的一件事是观看这Ҏ(gu)技术是如何执行在运行时从远E的 Web 服务器装入的代码。(此外Q还有更令h兴奋的事 -- Java 技术提供了一U便于编写代码的强大语言。)更一些o(h)人激动的是它可以执行从远E?Web 服务器通过 HTTP q接发送过来的字节码? 此项功能归功?Java 语言可以安装定制 ClassLoader。Applet 查看器包含一?ClassLoaderQ它不在本地文gpȝ中寻扄Q而是讉Kq程服务器上?Web 站点Q经q?HTTP 装入原始的字节码文gQƈ把它们{换成 JVM 内的cR? 览器和 Applet 查看器中?ClassLoaders q可以做其它事情Q它们支持安全性以?qing)不同?Applet 在不同的面上运行而互不干扰? Luke Gorrie ~写?Echidna 是一个开放源码包Q它可以使?zhn)在单个虚拟机上运行多?Java 应用E序。(请参?a >q一步了解和参考资?/a>。)它用定制的 ClassLoaderQ通过向每个应用程序提供该cL件的自n副本Q以防止应用E序互相q扰? 我们?ClassLoader CZ
了解?ClassLoader 如何工作以及(qing)如何~写 ClassLoader 之后Q我们将创徏UC CompilingClassLoader (CCL) ?Classloader。CCL 为我们编?Java 代码Q而无需要我们干涉这个过E。它基本上就cM于直接构建到q行时系l中?"make" E序? 注:(x)q一步了解之前,应注意在 JDK 版本 1.2 中已改进?ClassLoader pȝ的某些方面(?Java 2 q_Q。本教程是按 JDK 版本 1.0 ?1.1 写的Q但也可以在以后的版本中q行?/p>
Java 2 ?ClassLoader 的变?/a>描述?Java 版本 1.2 中的变动Qƈ提供了一些详l信息,以便修改 ClassLoader 来利用这些变动?
------------------------------------------------------------------------------------------------------
ClassLoader 的基本目标是对类的请求提供服务。当 JVM 需要用类Ӟ它根据名U向 ClassLoader hq个c,然后 ClassLoader 试图q回一个表C个类?Class
对象?
通过覆盖对应于这个过E不同阶D늚Ҏ(gu)Q可以创建定制的 ClassLoader?
在本章的其余部分Q?zhn)会(x)学?Java ClassLoader 的关键方法。?zhn)了解每一个方法的作用以及(qing)它是如何适合装入cL件这个过E的。?zhn)也?x)知道Q创q ClassLoader Ӟ需要编写什么代码?
在下一章中Q?zhn)?x)利用q些知识来用我们的 ClassLoader CZ -- CompilingClassLoader?
Ҏ(gu) loadClass
?Java 版本 1.1 和以前的版本中, Ҏ(gu)
Ҏ(gu)
对于定制?ClassLoaderQ只有在试其它Ҏ(gu)装入cM后,再? 其工作流E如下:(x) 在大多数定制 ClassLoaders 中,首先调用 Ҏ(gu) 正如前面所提到的,可以不完全地Q不带解析)装入c,也可以完全地Q带解析Q装入类。当~写我们自己? Ҏ(gu) l装 ClassLoader.loadClass()
?ClassLoader 的入口点。其特征如下Q?Class loadClass( String name, boolean resolve );
name
参数指定?JVM 需要的cȝ名称Q该名称以包表示法表C,?Foo
?java.lang.Object
?resolve
参数告诉Ҏ(gu)是否需要解析类。在准备执行cM前,应考虑c解析。ƈ不L需要解析。如?JVM 只需要知道该cL否存在或扑և该类的超c,那么׃需要解析?loadClass
Ҏ(gu)是创建定制的 ClassLoader 时唯一需要覆盖的Ҏ(gu)。(Java 2 ?ClassLoader 的变?/a>提供了关?Java 1.2 ?findClass()
Ҏ(gu)的信息。)
defineClass
defineClass
Ҏ(gu)?ClassLoader 的主要诀H。该Ҏ(gu)接受由原始字节组成的数组q把它{换成 Class
对象。原始数l包含如从文件系l或|络装入的数据?defineClass
理 JVM 的许多复杂、神U和倚赖于实现的斚w -- 它把字节码分析成q行时数据结构、校验有效性等{。不必担心,(zhn)无需亲自~写它。事实上Q即使?zhn)惌q么做也不能覆盖它,因ؓ(f)它已被标记成最l的?
findSystemClass
findSystemClass
Ҏ(gu)从本地文件系l装入文件。它在本地文件系l中LcLӞ如果存在Q就使用 defineClass
原始字节{换成 Class
对象Q以该文g转换成类。当q行 Java 应用E序Ӟq是 JVM 正常装入cȝ~省机制。(Java 2 ?ClassLoader 的变?/a>提供了关?Java 版本 1.2 q个q程变动的详l信息。) findSystemClass
。原因很单:(x)ClassLoader 是负责执行装入类的特D步骤,不是负责所?/em>cR例如,即 ClassLoader 从远E的 Web 站点装入了某些类Q仍焉要在本地机器上装入大量的基本 Java 库。而这些类不是我们所兛_的,所以要 JVM 以缺省方式装入它们:(x)从本地文件系l。这是 findSystemClass
的用途?
findSystemClass
Q它从文gpȝ装入该类?findSystemClass
以节省在本地可以装入的许多 Java 库类而要在远E?Web 站点上查找所q旉。然而,正如Q在下一章节所看到的,直到信能自动编译我们的应用E序代码Ӟ才让 JVM 从本地文件系l装入类?
resolveClass
loadClass
Ӟ可以调用 resolveClass
Q这取决?loadClass
?resolve
参数的倹{?/font>findLoadedClass
findLoadedClass
充当一个缓存:(x)当请?loadClass
装入cLQ它调用该方法来查看 ClassLoader 是否已装入这个类Q这样可以避免重新装入已存在cL造成的麻烦。应首先调用该方法?/font>
让我们看一下如何组装所有方法?
我们?loadClass
实现CZ执行以下步骤。(q里Q我们没有指定生成类文g是采用了哪种技?-- 它可以是?Net 上装入、或者从归档文g中提取、或者实时编译。无论是哪一U,那是U特D的奇方式Q我们获得了原始类文g字节。)
findLoadedClass
来查看是否存在已装入的类?br x="7" />
defineClass
它们{换成 Class
对象?br x="7" />
findSystemClass
查看是否从本地文件系l获取类?br x="7" />
resolve
参数?true
Q那么调?resolveClass
解析 Class
对象?br x="7" />
ClassNotFoundException
?br x="7" />
W三章:(x)Compiling ClassLoader CCL 揭密
我们?ClassLoader (CCL) 的Q务是保代码被编译和更新? 下面描述了它的工作方式:(x)
在深入讨Z前,应该先退一步,讨论 Java ~译。通常QJava ~译器不只是~译(zhn)要求它~译的类。它q会(x)~译其它c,如果q些cL(zhn)要求编译的cL需要的cR? CCL 逐个~译应用E序中的需要编译的每一个类。但一般来_(d)在编译器~译完第一个类后,CCL ?x)查找所有需要编译的c,然后~译它。ؓ(f)什么?Java ~译器类g我们正在使用的规则:(x)如果cM存在Q或者与它的源码相比Q它比较旧,那么它需要编译。其实,Java ~译器在 CCL 之前的一个步骤,它会(x)做大部分的工作? ?CCL ~译它们Ӟ?x)报告它正在~译哪个应用E序上的cR在大多数的情况下,CCL ?x)在E序中的ȝ上调用编译器Q它?x)做完所有要做的 -- ~译器的单一调用已够了? 然而,有一U情形,在第一步时不会(x)~译某些cR如果? 使用 CompilationClassLoader
要?CCLQ必MҎ(gu)方式调用E序。不能直接运行该E序Q如Q? 应以下列方式q行它:(x) CCLRun 是一个特D的存根E序Q它创徏 CompilingClassLoader q用它来装入E序的主c,以确保通过 CompilingClassLoader 来装入整个程序。CCLRun 使用 Java Reflection API 来调用特定类的主Ҏ(gu)q把参数传递给它。有兌l信息,请参?a >源代?/a>? q行CZ
源码包括了一l小c,它们演示了工作方式。主E序? h意,首先调用~译器, -------------------------------------------------------------------------------------- W四章:(x)java2 中ClassLoader的变?/strong> 概述
?Java 版本 1.2 和以后的版本中,?ClassLoader 做了一些改q。Q何ؓ(f)老系l编写的代码可以在新版本中运行,但新pȝ为?zhn)提供了一些便利? 新模型是委托模型Q这意味着如果 ClassLoader 不能扑ֈc,它会(x)h父代 ClassLoader 来执行此Q务。所?ClassLoaders 的根是系l?ClassLoaderQ它?x)以~省方式装入c?-- 卻I从本地文件系l?
定制~写? ?Java 1.2 ? q种方式的好处是(zhn)可能不一定要覆盖 新方法:(x) 新方法:(x) 如果覆盖 新方法:(x)
Z类h委托l父?ClassLoaderQ这个新Ҏ(gu)允许 ClassLoader 获取它的父代 ClassLoader。当使用Ҏ(gu)Ҏ(gu)Q定制的 ClassLoader 不能扑ֈcLQ可以用这U方法? 父代 ClassLoader 被定义成创徏?ClassLoader 所包含代码的对象的 ClassLoader? ---------------------------------------------------------------------------------- W五?源代?/strong>
Java ~译的工作方?/strong>
ClassNotFoundException
?br x="7" />
findSystemClass
来寻找该cR?br x="7" />
ClassNotFoundException
?br x="7" />
Class.forName
Ҏ(gu)Q通过名称来装入类QJava ~译器会(x)不知道这个类时所需要的。在q种情况下,(zhn)会(x)看到 CCL 再次q行 Java ~译器来~译q个cR在源代?/a>中演CZq个q程?
% java Foo arg1 arg2
% java CCLRun Foo arg1 arg2
Foo
c,它创建类 Bar
的实例。类 Bar
创徏另一个类 Baz
的实例,它在 baz
包内Q这是ؓ(f)了展C?CCL 是如何处理子包里的代码?code style="font-size: 12px; font-family: Courier New,Courier,monospace">Bar 也是通过名称装入的,其名UCؓ(f) Boo
Q这用来展示它也能与 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
Ӟ被调用它Q这?CCL ?x)再ơ调用编译器来编译它?
loadClass
的缺省实?/strong>loadClass
Ҏ(gu)一般尝试几U方式来装入所h的类Q如果?zhn)~写许多c,?x)发Cơ次地在相同的、很复杂的方法上~写变量?loadClass
的实现嵌入了大多数查扄的一般方法,q(zhn)通过覆盖 findClass
Ҏ(gu)来定制它Q在适当的时?findClass
?x)调?loadClass
?loadClass
Q只要覆?findClass
p了,q减了工作量?
findClass
loadClass
的缺省实现调用这个新Ҏ(gu)?code style="font-size: 12px; font-family: Courier New,Courier,monospace">findClass 的用途包含?zhn)?ClassLoader 的所有特D代码,而无需要复制其它代码(例如Q当专门的方法失败时Q调用系l?ClassLoaderQ?/font>getSystemClassLoader
findClass
?loadClass
Q?code style="font-size: 12px; font-family: Courier New,Courier,monospace">getSystemClassLoader 使?zhn)能以实?ClassLoader
对象来访问系l?ClassLoaderQ而不是固定的?findSystemClass
调用它)?/font>getParent
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 object
Class 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 的源代码
Foo.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 的源代码
Bar.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 的源代码baz/Baz.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 的源代码
Boo.java
// $Id$
package baz;
public class Baz
{
public Baz( String a, String b ) {
System.out.println( "baz! "+a+" "+b );
}
}
以下?Boo.java 的源代码
// $Id$
public class Boo
{
public Boo() {
System.out.println( "Boo!" );
}
}
概述
J2EE开发h员经帔R要管理WebLogic Serverq调试WebLogic Server上部|的应用E序?WebLogic Server理控制台虽然能够启动和停止WebLogic ServerQ却不能讄JVM选项?a class="channel_keylink" target="_blank">服务?/a>c\径。必M用startWebLogic脚本来设|JVM选项和服务器c\径。而要调试WebLogic Server上部|的应用E序Q则需要带q程调试器的IDE.有了WebLogic插g后,可以通过Eclipse IDE理WebLogic Server. 在文本中Q我们将开发一个包括会(x)话EJB和servlet的J2EE应用E序、通过Eclipse IDE在WebLogic Server中部|应用程序、在Eclipse中调试应用程序?/p>
安装准备
下蝲q安装Eclipse 3.0 IDEQ?a >www.eclipse.org
下蝲q安装WebLogic Server 8.1Q?/p>
www.bea.com/framework.jspQCNT=index.htm&FP=/content/products/weblogic/server
安装WebLogic-Eclipse插g
现在安装WebLogic-Eclipse IDE.在Eclipse IDE上,选择Help>Software Updates>Find and InstallQ将昄Install/UpdateH体。选择Search for new features to installQ然后单击Next按钮。在昄的InstallH体中,单击New Remote Site按钮指定要从其安装插件的更新Web站点。在New Update SiteH体中,指定名称和安装WebLogic-Eclipse插g的URL.WebLogic-Eclipse插g的URL?
选择许可条款q单击Next按钮。在Install locationH体中指定将安装WebLogic-Eclipse插g的目录。单击Finish按钮完成WebLogic插g的配|。在昄的JAR VerificationH体中,单击Install按钮安装WebLogic-Eclipse插g。重启Eclipse工作台完成插件安装。现在WebLogic-Eclipse插g便安装在 Eclipse IDE中了。Eclipse中新MRun>Start WebLogic和Run>Stop WebLogic两个功能?/p>
配置WebLogic-Eclipse插g 安装了WebLogic-Eclipse插g后,我们在Eclipse IDE中配|该插g。首先,创徏一个用于配|WebLogic插g的项目。选择File>New>Project.在New ProjectH体中选择Java>Java ProjectQ然后单击Next按钮。在Create a Java projectH体中指定项目名Uͼ然后单击Next按钮。在Java SettingsH体中ؓ(f)目d源文件夹。单击Add Folder按钮。在New Source FolderH体中指定文件夹名称。出C个消息窗体提C|bin文g夹作为构出文件夹。接下来Q添加项目所需的库。示例应用程序需要在c\径中dJ2EE JAR.选择Libraries选项卡,然后单击Add External JARs按钮?/p>
为项目添加J2EE 1.4 j2ee.jar文g?.4 j2ee.jar在目库中列出。单击Finish按钮完成目配置。这样便一个项目添加到Eclipse IDE Package Explorer视图中?/p>
接下来指定WebLogic Server配置。选择Window>Preferences.在出现的PreferencesH体中,选择WebLogic节点。在WebLogic preference面Q选择要配|的WebLogic Server版本。指定不同的字段|?? 所C。由于安装服务器和配|域的目录不同,g有所不同。单击Apply按钮应用指定的倹{?/p>
字段描述?/strong> ? WebLogic-Eclipse插g 如果必须向服务器c\径添加JAR文gQ请选择WebLogic>Classpath节点。可以在dWebLogic库之前或之后dJAR/Zip文g或目录。选择WebLogic>JavaVM Options节点指定JavaVM选项。例如,修改weblogic.ProductionModeEnabled属性。将属性D|ؓ(f)false可用开发模式启动服务器。单击Apply按钮应用JavaVM选项?/p>
接下来,指定要用WebLogic Server配置q行调试的项目。单击Add按钮Q选择要添加到插g配置的项目。若要调试某个项目,该项目必M于插仉|中。单击OK按钮?/p>
q样便将选择的项目添加到目列表中了。单击Apply按钮Q然后单击OK按钮Q用项目和W(xu)ebLogic Server完成WebLogic插g的配|?/p>
开发和调试WebLogic应用E序 配置了WebLogic插g后,开发一个J2EE应用E序在WebLogic Server中进行部|和调试。示例J2EE应用E序由Session EJB和客L(fng)servletl成。可从资源zip文g中获取该 J2EE应用E序Q关于本文的源代码,可在U查看WLDJ归档文g中的文章 http://wldj.sys-con.com/read/issue/archives/QVol. 5Qiss. 2Q。将资源zip文g提取到目录。在上文中配|的Eclipse目EclipseWebLogic中,选择File>Import导入J2EE应用E序的src目录。在ImportH体中,选择File System节点Q然后单击Next按钮。在File systemH体中,选择directories/filesd目Q然后单击Finish按钮Q见?Q?/p>
? q样便将CZJ2EE应用E序文gd到项目中。用Ant build.xml文g构徏目。右键单击build.xmlQ选择Run>Ant Build卛_构徏J2EE应用E序q将光|在WebLogic Server应用E序目录中。接下来Q选择Run>Start WebLogic在Eclipse IDE中启动WebLogic Server.q样便将Session EJB/Servlet应用E序部v?WebLogic Server中,如应用程序节Ҏ(gu)C?/p>
在浏览器中输入URL http://localhostQ?001/weblogic/webLogicPlug-inq行W(xu)ebLogicServlet. servlet的输出将在浏览器中显C。接下来向客L(fng)servletd一个异常(NullPointerExceptionQ,以验证WebLogic插g的调试功能。在WebLogicServlet servlet中将Q?/p>
out.printlnQsessionEJB.getEclipsePlug-inQ)Q; 替换为:(x) String str=nullQ?/p>
out.printlnQstr.toStringQ)Q; 选择Run>Add Java Exception Breakpoint向servletd一个断炏V在Add Java Exception BreakpointH体中,选择NullPointerException.删除之前构徏的目录ƈ使用build.xml构徏应用E序。选择Debug perspective.在Debug perspective可以看到WebLogic Server正运行在localhostL中?/p>
在浏览器中运行示例servletQ带NullPointerExceptionQ。因为servlet带有异常Q所以服务器被中断,q且Debug perspective昄NullPointerException.使用Run菜单中的调试功能可以调试应用程序?/p>
l束?/p>
lg所qͼ使用WebLogic插g可以通过Eclipse IDE理WebLogic ServerQ还可通过Eclipse IDE调试服务器中部v的应用程序。WebLogic插g的局限性在于不支持JSP调试。该插g?.0版本有更多功能?/p>
J2EE配置WebLogic-Eclipse插g