Java
源码改动办法
先前我曾提到,原本想借由“改动
Java
标准库源码”来测知
Class
object
的生成,但由于其
ctor
原始设计为
private
,也就是说不可能透过这个管道生成
Class
object
(而是由
class loader
负责生成),因此“在
ctor
中
打印出某种信息”的企图也就失去了意义。
这里我要谈点题外话:如何修改
Java
标准库源码并让它反应到我们的应用程序来。假设我想修改
java.lang.Class
,让它在某些情况下打印某种信息。首先必须找出标准源码!当你下载
JDK
套件并安装妥当,你会发现
jdk150\src\java\lang
目录(见
图
10
)之中有
Class.java
,这就是我们此次行动的标准源码。备份后加以修改,编译获得
Class.class
。接下来准备将
.class
搬移到
jdk150\jre\lib\endorsed
(见
图
10
)。
这是一个十分特别的目录,
class loader
将优先从该处读取内含
classes
的
.jar
文件
——
成功的条件是
.jar
内的
classes
压缩路径必须和
Java
标准库的路径完全相同。为此,我们可以将刚才做出的
Class.class
先搬到一个为此目的而刻意做出来的
\java\lang
目录中,压缩为
foo.zip
(任意命名,唯需夹带路径
java\lang
),再将这个
foo.zip
搬到
jdk150\jre\lib\endorsed
并改名为
foo.jar
。此后你的应用程序便会优先用上这里的
java.lang.Class
。整个过程可写成一个批处理文件(
batch file
),如
图
11
,在
DOS Box
中使用。
图
10
:
JDK1.5
安装后的目录组织。其中的
endorsed
是我新建。
del e:\java\lang\*.class //
清理干净
del c:\jdk150\jre\lib\endorsed\foo.jar //
清理干净
c:
cd c:\jdk150\src\java\lang
javac -Xlint:unchecked Class.java
//
编译源码
javac -Xlint:unchecked ClassLoader.java /
/
编译另一个源码(如有必要)
move *.class e:\java\lang //
搬移至刻意制造的目录中
e:
cd e:\java\lang //
以下压缩至适当目录
pkzipc
-add -path=root
c:\jdk150\jre\lib\endorsed\foo.jar
*.class
cd e:\test //
进入测试目录
javac -Xlint:unchecked Test.java //
编译测试程序
java Test //
执行测试程序
图
11
:一个可在
DOS Box
中使用的批处理文件(
batch file
),用以自动化
java.lang.Class
的修改动作。
Pkzipc(.exe)
是个命令列压缩工具,
add
和
path
都是其命令。
更多信息
以下是视野所及与本文主题相关的更多讨论。这些信息可以弥补因文章篇幅限制而带来的不足,或带给您更多视野。
l
"
Take an in-depth look at the Java Reflection API -- Learn about the new Java 1.1 tools forfinding out information about classes
", by Chuck McManis
。此篇文章所附程序代码是本文示例程序的主要依据(本文示例程序示范了更多
Reflection APIs
,并采用
JDK1.5
新式的
for-loop
写法)。
l
"
Take a look inside Java classes -- Learn to deduce properties of a Java class from inside aJava program
", by Chuck McManis
。
l
"
The basics of Java class loaders -- The fundamentals of this key component of the Javaarchitecture
", by Chuck McManis
。
l
《
The Java Tutorial Continued
》
, Sun microsystems. Lesson58-61, "Reflection".
注
1
用过诸如
MFC
这类所谓
Application Framework
的程序员也许知道,
MFC
有所谓的
dynamic creation
。但它并不等同于
Java
的动态加载或动态辨识;所有能够在
MFC
程序中起作用的
classes
,都必须先在编译期被编译器
“
看见
”
。
注
2
如果操作对象是
Object
,
Class.getSuperClass()
会返回
null
。