面试的曲折

08-11-27 IceQi

面试了一个地方做银行支付系统的,对方的技术人员最后问我“能不能加载一个自己重写的java.lang.String”。我想到的第一个回答是“有什么可能需要重写java.lang.String”,想了想还是没说。

xmuzyu
2008-11-28 01:22

不可能啊,类加载器的安全模型不同意。

IceQi
2008-11-28 09:23

加载是可以的,只需要自己重写一个classloader,但是被系统应用又是另外的事情了,看看下面的程序。我说这些的目的不是在讨论写一个自己的Integer或者String,其实是思考角度的问题。

站在应用Java做业务过程角度上其实不需要过分的关注Java是怎么实现安全管理的,因为在应用中根本就不应该考虑这种替换核心类的实现方式。

public class SimpleClassLoader extends ClassLoader {

private Hashtable classes = new Hashtable();

public SimpleClassLoader() {

}

/**

* This sample function for reading class implementations reads

* them from the local file system

*/

private byte getClassImplFromDataBase(String className)[] {

System.out.println(" >>>>>> Fetching the implementation of "+className);

byte result[];

try {

String path = null;

if(!className.equalsIgnoreCase("java/lang/Integer"))

{

path = "bin/ClassLoader/" + className+".class";

}

else

{

path = "bin/" + className+".class";

}

FileInputStream fi = new FileInputStream(path);

result = new byte[fi.available()];

fi.read(result);

return result;

} catch (Exception e) {

/*

* If we caught an exception, either the class wasnt found or it

* was unreadable by our process.

*/

return null;

}

}

/**

* This is a simple version for external clients since they

* will always want the class resolved before it is returned

* to them.

*/

public Class loadClass(String className) throws ClassNotFoundException {

return (loadClass(className, true));

}

/**

* This is the required version of loadClass which is called

* both from loadClass above and from the internal function

* FindClassFromClass.

*/

public synchronized Class loadClass(String className, boolean resolveIt)

throws ClassNotFoundException {

Class result;

byte classData[];

System.out.println(" >>>>>> Load class : "+className);

/* Check our local cache of classes */

result = (Class)classes.get(className);

if (result != null) {

System.out.println(" >>>>>> returning cached result.");

return result;

}

/* Check with the primordial class loader */

try {

if(!className.equalsIgnoreCase("java/lang/Integer"))

{

result = super.findSystemClass(className);

System.out.println(" >>>>>> returning system class (in CLASSPATH).");

return result;

}

} catch (ClassNotFoundException e) {

System.out.println(" >>>>>> Not a system class.");

}

/* Try to load it from our repository */

classData = getClassImplFromDataBase(className);

if (classData == null) {

throw new ClassNotFoundException();

}

/* Define it (parse the class file) */

result = defineClass(classData, 0, classData.length);

if (result == null) {

throw new ClassFormatError();

}

if (resolveIt) {

resolveClass(result);

}

classes.put(className, result);

System.out.println(" >>>>>> Returning newly loaded class.");

return result;

}

=============================================================================

package java.lang;

public class Integer

{

public String toString()

{

return "mine";

}

}

===============================================================================

public class TestClass{

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

{

SimpleClassLoader sc = new SimpleClassLoader();

Object o;

o = (sc.loadClass("java/lang/Integer")).newInstance();

o.toString();

}

}

xmuzyu
2008-11-28 14:48

呵呵,LS的classLoader可以说不是一个完整的classLoader,真的classLoader是有委托模型的,是要指定父子关系,只要指定了父子关系,那么就不可能通过自己写的classLoader来加载与类库同名的类了,因为加载顺序是先父加载器后子加载器。

IceQi
2008-11-28 14:57

没错的,这个方式下class被加载起来了,但是还不可能被真正的用起来,我这么写一个也仅仅是为了娱乐。

我发这个帖子也不是为了讨论技术,算是放水发个牢骚吧,这不是杂类么。

2Go 1 2 下一页