objectemitter.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 323 行
JAVA
323 行
/**
* $Id: ObjectEmitter.java,v 1.4 2004/02/15 11:08:16 epr Exp $
*/
package org.jnode.build;
import java.io.PrintWriter;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Set;
import org.jnode.assembler.BootImageNativeStream;
import org.jnode.assembler.NativeStream;
import org.jnode.assembler.x86.X86Stream;
import org.jnode.vm.BootableObject;
import org.jnode.vm.VmSystemObject;
import org.jnode.vm.classmgr.VmClassLoader;
import org.jnode.vm.classmgr.VmClassType;
import org.jnode.vm.classmgr.VmType;
public class ObjectEmitter {
private final VmClassLoader loaderContext;
private final NativeStream os;
private final BootImageNativeStream bis;
private final PrintWriter debugWriter;
private final Set legalInstanceClasses;
/**
* Construct a new ObjectEmitter *
*
* @param b
* @param os
* @param debug
* @param legalInstanceClasses
*/
public ObjectEmitter(VmClassLoader b, NativeStream os, PrintWriter debug, Set legalInstanceClasses) {
this.loaderContext = b;
this.os = os;
this.bis = (BootImageNativeStream)os;
this.legalInstanceClasses = legalInstanceClasses;
this.debugWriter = debug;
}
/**
* Write the header and the contents of an object to the native stream.
* @param obj
* @throws BuildException
* @throws ClassNotFoundException
*/
public final void emitObject(Object obj) throws BuildException, ClassNotFoundException {
if (obj == null) {
return;
}
final Class cls = obj.getClass();
testForValidEmit(obj);
if (debugWriter != null) {
debugWriter.println("$" + Integer.toHexString(os.getLength()));
if (obj instanceof char[]) {
final char[] a = (char[]) obj;
for (int i = 0; i < a.length; i++) {
debugWriter.print("'" + a[i] + "' ");
}
debugWriter.println();
} else if (obj instanceof byte[]) {
final byte[] a = (byte[]) obj;
for (int i = 0; i < a.length; i++) {
debugWriter.print("" + a[i] + ' ');
}
debugWriter.println();
} else {
debugWriter.println(obj);
}
}
if (obj instanceof VmSystemObject) {
((VmSystemObject) obj).verifyBeforeEmit();
}
// Writeout the header
final VmClassType vmClass = (VmClassType) loaderContext.loadClass(cls.getName(), true);
vmClass.incInstanceCount();
final X86Stream.ObjectInfo oInfo = os.startObject(vmClass);
os.setObjectRef(obj);
// If the object is a VmClass, force the loading of the
// correspondig java.lang.Class
if (cls.equals(VmType.class)) {
VmType vmCls = (VmType) obj;
String name = vmCls.getName().replace('/', '.');
if (!name.startsWith("java.lang")) {
vmCls.asClassDuringBootstrap();
}
}
// Writeout object contents
if (cls.equals(String.class)) {
emitString((String) obj);
} else if (cls.equals(Integer.class)) {
emitInteger((Integer) obj);
} else if (cls.equals(Long.class)) {
emitLong((Long) obj);
} else if (cls.equals(Class.class)) {
emitClass((Class) obj);
} else if (cls.isArray()) {
emitArray(cls, obj);
} else {
emitObject(cls, obj);
}
oInfo.markEnd();
if (debugWriter != null) {
debugWriter.println();
}
}
/**
* Is it legal to emit the given object?
*
* @param object
* @throws BuildException
* Is if not valid to emit the given object into the boot image.
*/
private final void testForValidEmit(Object object) throws BuildException {
if (object == null) {
return;
} else if (object instanceof BootableObject) {
return;
} else if (object.getClass().isArray()) {
return;
} else {
final String clsName = object.getClass().getName().replace('/', '.');
/*
* if (clsName.startsWith("org.jnode.")) { return;
*/
if (legalInstanceClasses.contains(clsName)) {
return;
}
/*
* final Class javaClass = object.getClass(); try { final VmClassType vmClass =
* (VmClassType)loaderContext.loadClass(javaClass.getName(), true);
* testClassCompatibility(javaClass, vmClass); System.out.println("Found compatible
* class " + clsName); legalInstanceClasses.add(clsName); } catch
* (ClassNotFoundException ex) { throw new BuildException("VmClass not found for " +
* clsName, ex);
*/
throw new BuildException("Cannot emit object of type " + clsName);
}
}
private void emitClass(Class c) throws BuildException {
try {
if (!c.isPrimitive()) {
// This layout should match the order and type of fields
// in java.lang.Class
// vmClass
bis.writeObjectRef(loaderContext.loadClass(c.getName(), true));
// declaredConstructors
bis.writeObjectRef(null);
// declaredFields;
bis.writeObjectRef(null);
// declaredMethods;
bis.writeObjectRef(null);
// fields;
bis.writeObjectRef(null);
// methods;
bis.writeObjectRef(null);
// interfaces;
bis.writeObjectRef(null);
// defaultConstructor;
bis.writeObjectRef(null);
// name
bis.writeObjectRef(null);
}
} catch (ClassNotFoundException ex) {
throw new BuildException("emitting object: [" + c + "]", ex);
}
}
private void emitString(String s) throws BuildException {
// This layout should match the order and type of fields
// in java.lang.String
bis.writeObjectRef(s.toCharArray()); // char[] value
os.write32(s.length()); // int count
os.write32(s.hashCode()); // int cachedHashCode
os.write32(0); // int offset
}
private void emitInteger(Integer i) throws BuildException {
// This layout should match the order and type of fields
// in java.lang.Integer
os.write32(i.intValue()); // int value
}
private void emitLong(Long l) throws BuildException {
// This layout should match the order and type of fields
// in java.lang.Long
os.write64(l.longValue()); // long value
}
private void emitArray(Class cls, Object obj) {
final Class cmpType = cls.getComponentType();
final int len = Array.getLength(obj);
os.write32(len);
if (cmpType == byte.class) {
final byte[] a = (byte[]) obj;
os.write(a, 0, len);
} else if (cmpType == boolean.class) {
final boolean[] a = (boolean[]) obj;
for (int i = 0; i < len; i++) {
os.write8(a[i] ? 1 : 0);
}
} else if (cmpType == char.class) {
final char[] a = (char[]) obj;
for (int i = 0; i < len; i++) {
os.write16(a[i]);
}
} else if (cmpType == short.class) {
final short[] a = (short[]) obj;
for (int i = 0; i < len; i++) {
os.write16(a[i]);
}
} else if (cmpType == int.class) {
final int[] a = (int[]) obj;
for (int i = 0; i < len; i++) {
os.write32(a[i]);
}
} else if (cmpType == long.class) {
final long[] a = (long[]) obj;
for (int i = 0; i < len; i++) {
os.write64(a[i]);
}
} else if (cmpType == float.class) {
final float[] a = (float[]) obj;
for (int i = 0; i < len; i++) {
os.write32(Float.floatToRawIntBits(a[i]));
}
} else if (cmpType == double.class) {
final double[] a = (double[]) obj;
for (int i = 0; i < len; i++) {
os.write64(Double.doubleToRawLongBits(a[i]));
}
} else {
final Object[] a = (Object[]) obj;
for (int i = 0; i < len; i++) {
bis.writeObjectRef(a[i]);
}
}
}
private void emitObject(Class cls, Object obj) throws BuildException {
final Class sCls = cls.getSuperclass();
if (sCls != null) {
emitObject(sCls, obj);
}
try {
final Field fields[] = cls.getDeclaredFields();
final int len = fields.length;
AccessibleObject.setAccessible(fields, true);
for (int i = 0; i < len; i++) {
final Field f = fields[i];
final int modifiers = f.getModifiers();
if ((modifiers & Modifier.STATIC) != 0) {
continue;
}
final Class fType = f.getType();
if ((modifiers & Modifier.TRANSIENT) != 0) {
if ((fType == long.class) || (fType == double.class)) {
os.write64(0);
} else {
os.write32(0);
}
if (debugWriter != null) {
debugWriter.println(f.getName() + " transient: 0");
}
} else if (fType.isPrimitive()) {
if (debugWriter != null) {
debugWriter.println(f.getName() + " " + f.get(obj));
}
if (fType == byte.class) {
os.write32(f.getByte(obj));
} else if (fType == boolean.class) {
os.write32((f.getBoolean(obj)) ? 1 : 0);
} else if (fType == char.class) {
os.write32(f.getChar(obj));
} else if (fType == short.class) {
os.write32(f.getShort(obj));
} else if (fType == int.class) {
os.write32(f.getInt(obj));
} else if (fType == float.class) {
os.write32(Float.floatToIntBits(f.getFloat(obj)));
} else if (fType == long.class) {
os.write64(f.getLong(obj));
} else if (fType == double.class) {
os.write64(Double.doubleToLongBits(f.getDouble(obj)));
} else {
throw new BuildException("Unknown primitive class " + fType.getName());
}
} else {
final Object value = f.get(obj);
try {
testForValidEmit(value);
} catch (BuildException ex) {
throw new BuildException("Cannot emit field " + f.getName() + " of class " + cls.getName(), ex);
}
bis.writeObjectRef(value);
}
}
} catch (IllegalAccessException ex) {
throw new BuildException("emitting object: [" + obj + "]", ex);
} catch (SecurityException ex) {
throw new BuildException("emitting object: [" + obj + "]", ex);
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?