实现的程序描述:
通过网络传输多个序列化的类, 不直接用ObjectOutputStream,要对它进一步
的封装,需重写annotate()方法,我想问一下,这个方法如何使用,是什么意思?\
当传输到另一台机器时,需利用ClassLoader类进行动态加载.
这里面好多问题不懂,希望各位提供一些资料,最好有一些实例说明.
手头资料不多,不知从何看起,望大家指点!
通过网络传输多个序列化的类, 不直接用ObjectOutputStream,要对它进一步
的封装,需重写annotate()方法,我想问一下,这个方法如何使用,是什么意思?\
当传输到另一台机器时,需利用ClassLoader类进行动态加载.
这里面好多问题不懂,希望各位提供一些资料,最好有一些实例说明.
手头资料不多,不知从何看起,望大家指点!
解决方案 »
- 程序输出疑问?
- java排序问题
- 重启网卡驱动的方法,要求使用程序实现,不管是调用cmd命令,还是c语言,或者java语言,谢谢!
- 关于java接收超出范围的数值问题
- FileInput(),FileOutput(),KeyboardInput()要怎么样才能用啊?是要加载什么吗?
- java中有没有vb里的MsgBox?
- 为什么我把class文件都用jar.exe打包成jar文件,双击文件但不能运行?
- SOS!!! 海量数据db to db 利用JDBC转移如何提高速度问题
- 关于动态绑定与上溯的问题,在线等候
- JAVA菜鸟的疑问:开发环境!!!!!!!!!!
- JAVA基本知识,有关运行环境的问题
- 问一个关于java语言的比较特殊的用法
因为每个JVM的类实现机制不同,所以序列化一个对象时,并未将一个这个对象的类的相应的对象(假设序列化对象是java.io.File的一个对象,这里所谓的对象的类的相应的对象就是Class.forName("java.io.File")的返回值)写入序列化流,因为一个JVM可能不能对另外一个JVM的Class对象反序列化。但你会发现一个奇怪的现象,就是java.lang.Class类事实上是实现了java.io.Serializable接口的,也就是说一个Class是可以被序列化的。是的,是可以序列化,但序列化一个Class对象事实上是序列化的这个Class对象相应的java.io.ObjectStreamClass对象。反序列化这个Class对象时,缺省时会在本地classpath中查找这个Class对象相应的类的sourceCode,比如说查找java/io/File.class文件,如果找到了sourceCode,则利用这个sourceCode来生成相应的类的对象。
所以序列化一个对象,是先把这个对象的类相应的ObjectStreamClass对象序列化到流中。然后再写入这上对象的内容。
反序列化时,如果在本地找不到这个对象的类的sourceCode,则序列化就会失败。但是我们可以通过覆盖ObjectOutputStream.annotateClass和ObjectInputStream.resolveClass来实现从服务器将类的sourceCode传到客户端(在annotateClass方法中,通过传入的类对象,调用classObj.getProtectionDomain().getCodeSource().getLocation().openStream();可以得到类的sourceCode输入流,将这个流写入到输出流),然后在客户端在方法ObjectInputStream.resolveClass中读取到这个sourceCode,并运用ClassLoader来载入这个类。
请参见ObjectOutputStream和ObjectInputStream的文档。
还有那个获取codeSource的代码也错了。丢
写个例子:
package whodsow.io;public interface Person
{
public String getName();
public int getAge();
}这个接口在客户端的classpath中也应该存在。即这个接口可以让JVM用缺省的方法载入。package whodsow.io;
import java.io.Serializable;public class Student implements Serializable
{
private String name;
private int age;
public Student(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}//自定义一个序列化类
package whodsow.io;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;/**
*
* @author 胡洲
*/
public static class MyObjectOutputStream extends ObjectOutputStream
{
public MyObjectOutputStream(OutputStream os)throws IOException
{
super(os);
} protected void annotateClass(Class c)throws IOException
{
if(c == Student.class)
{
//计算类的codeSource文件,这里的计算结果是相对于一个classpath
//的相对路径
String relativeFile
= c.getName().replace('.', File.separatorChar)
+ ".class";
//找一个类装载器来获取这个codeSource的输入流
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream is = cl.getResourceAsStream(relativeFile);
byte[] bs = is.available();
is.read(bs); //将Student.class文件的内容写入到输出流中,这里这个输出流,也是序列化对象时
//底层的输出流
this.writeObject(bs);
}
}
}//反序列化类
package whodsow.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;/**
*
* @author 胡洲
*/
public class MyObjectInputStream extends ObjectInputStream
{
public MyObjectInputStream(InputStream is)throws IOException
{
super(is);
} protected Class resolveClass(ObjectStreamClass osc)
throws IOException, ClassNotFoundException
{
String name = osc.getName();
if(name.startsWith("whodsow.io."))
{
System.out.println("resolve class: " + name);
byte[] codeSource = (byte[])this.readObject();
return MyClassLoader.loadClass(name, codeSource);
}
else
{
return super.resolveClass(osc);
}
}
}//类装载器
package whodsow.io;/**
*
* @author 胡洲
*/
public class MyClassLoader extends ClassLoader
{
private MyClassLoader()
{
super(Thread.currentThread().getContextClassLoader());
} public static Class loadClass(String name, byte[] codeSource)
{
Class c
= new MyClassLoader().defineClass(name, codeSource, 0,
codeSource.length);
System.out.println("load class: " + c.getName() + " over...");
return c;
}
}//test类
package whodsow.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;/**
*
* @author 胡洲
*/
public class Test
{
public static void main(String[] args)
{
try
{
Person p = new Student("whodsow", 24);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
ObjectOutputStream oos = new MyObjectOutputStream(buffer);
oos.writeObject(p);
oos.close();
InputStream is = new ByteArrayInputStream(buffer.toByteArray());
ObjectInputStream ois = new MyObjectInputStream(is);
p = (Person)ois.readObject();
ois.close();
System.out.println(p.getName() + " " + p.getAge());
}
catch (IOException e)
{
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
}