abstractbootimagebuilder.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 1,109 行 · 第 1/3 页
JAVA
1,109 行
* @param os
* @throws BuildException
*/
protected abstract void copyKernel(NativeStream os) throws BuildException;
/**
* Align the stream on a page boundary
*
* @param os
* @throws BuildException
*/
protected abstract void pageAlign(NativeStream os) throws BuildException;
/**
* Copy the jnode.jar file into a byte array that is added to the java
* image.
*
* @param os
* @throws BuildException
*/
protected final void copyJarFile(NativeStream os) throws BuildException {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileInputStream fis = new FileInputStream(jarFile);
final byte[] buf = new byte[ 4096];
int len;
while ((len = fis.read(buf)) > 0) {
bos.write(buf, 0, len);
}
fis.close();
bos.close();
final byte[] systemRtJar = bos.toByteArray();
os.getObjectRef(systemRtJar);
clsMgr.setSystemRtJar(systemRtJar);
} catch (IOException ex) {
throw new BuildException(ex);
}
}
/**
* Emit code to bootstrap the java image
*
* @param os
* @param clInitCaller
* @param vm
* @param pluginRegistry
* @throws BuildException
*/
protected abstract void initImageHeader(NativeStream os,
Label clInitCaller, Vm vm, PluginRegistry pluginRegistry)
throws BuildException;
/**
* Create the initial stack space.
*
* @param os
* @param stackLabel
* Label to the start of the stack space (low address)
* @param stackPtrLabel
* Label to the initial stack pointer (on x86 high address)
* @throws BuildException
* @throws ClassNotFoundException
* @throws UnresolvedObjectRefException
*/
protected abstract void createInitialStack(NativeStream os,
Label stackLabel, Label stackPtrLabel) throws BuildException,
ClassNotFoundException, UnresolvedObjectRefException;
/**
* Link all undefined symbols from the kernel native code.
*
* @param os
* @throws ClassNotFoundException
* @throws UnresolvedObjectRefException
*/
protected abstract void linkNativeSymbols(NativeStream os)
throws ClassNotFoundException, UnresolvedObjectRefException;
protected abstract void emitStaticInitializerCalls(NativeStream os,
VmType[] bootClasses, Object clInitCaller)
throws ClassNotFoundException;
/**
* Emit all objects to the native stream that have not yet been emitted to
* this stream.
*
* @param os
* @param arch
* @param blockObjects
* @throws BuildException
*/
private final void emitObjects(NativeStream os, VmArchitecture arch,
Set blockObjects) throws BuildException {
log("Emitting objects", Project.MSG_DEBUG);
PrintWriter debugOut = null;
final TreeSet emittedClassNames = new TreeSet();
try {
if (debug) {
debugOut = new PrintWriter(new FileWriter(debugFile, true));
}
final ObjectEmitter emitter = new ObjectEmitter(clsMgr, os,
debugOut, legalInstanceClasses);
final long start = System.currentTimeMillis();
int cnt = 0;
int lastUnresolved = -1;
int loops = 0;
while (true) {
loops++;
compileClasses(os, arch);
final Collection objectRefs = new ArrayList(os.getObjectRefs());
int unresolvedFound = 0; // Number of unresolved references
// found in the following
// loop
int emitted = 0; // Number of emitted objects in the following
// loop
for (Iterator i = objectRefs.iterator(); i.hasNext();) {
X86Stream.ObjectRef ref = (X86Stream.ObjectRef) i.next();
if (!ref.isResolved()) {
final Object obj = ref.getObject();
if (!(obj instanceof Label)) {
unresolvedFound++;
if (obj instanceof VmType) {
final VmType vmtObj = (VmType) obj;
vmtObj.link();
if (!vmtObj.isCompiled()) {
compileClasses(os, arch);
}
}
boolean skip;
if (blockObjects == null) {
skip = false;
} else {
skip = blockObjects.contains(obj);
}
/*
* if (obj instanceof VmMethod) { final VmMethod
* mObj = (VmMethod)obj; if (!mObj.hasNativeCode()) {
* compileClasses(os, arch); } if
* (!mObj.getDeclaringClass().isCompiled()) {
* log("Oops"); }
*/
if (!skip) {
if (blockObjects == null) {
emittedClassNames.add(obj.getClass()
.getName());
//log("emitObject " +
// obj.getClass().getName());
}
//if (obj != skipMe) {
emitter.emitObject(obj);
emitted++;
X86Stream.ObjectRef newRef = os
.getObjectRef(obj);
if (ref != newRef) { throw new RuntimeException(
"Object has changed during emitObject! type="
+ obj.getClass().getName()); }
if (!ref.isResolved()) { throw new RuntimeException(
"Unresolved reference to object "
+ ((obj == null) ? "null" : obj
.getClass().getName())); }
}
}
}
}
if (unresolvedFound == lastUnresolved) {
if (unresolvedFound == 0) {
break;
}
if (blockedObjects != null) {
if (unresolvedFound == (emitted + blockObjects.size())) {
//log("UnresolvedFound " + unresolvedFound + ",
// emitted " + emitted + ",blocked " +
// blockObjects.size());
break;
}
if ((emitted == 0) && !blockObjects.isEmpty()) {
break;
}
}
}
lastUnresolved = unresolvedFound;
cnt += emitted;
}
final long end = System.currentTimeMillis();
log("Emitted " + cnt + " objects, took " + (end - start) + "ms in "
+ loops + " loops");
if (debugOut != null) {
debugOut.close();
debugOut = null;
}
if (blockObjects == null) {
log("Emitted classes: " + emittedClassNames,
Project.MSG_VERBOSE);
}
} catch (ClassNotFoundException ex) {
throw new BuildException(ex);
} catch (IOException ex) {
throw new BuildException(ex);
}
}
/**
* Load a VmClass for a given java.lang.Class
*
* @param c
* @return The loaded class
* @throws ClassNotFoundException
*/
public final VmType loadClass(Class c) throws ClassNotFoundException {
String name = c.getName();
VmType cls = clsMgr.findLoadedClass(name);
if (cls != null) {
return cls;
} else if (c.isPrimitive()) {
if ("boolean".equals(name)) {
cls = VmType.getPrimitiveClass('Z');
} else if ("byte".equals(name)) {
cls = VmType.getPrimitiveClass('B');
} else if ("char".equals(name)) {
cls = VmType.getPrimitiveClass('C');
} else if ("short".equals(name)) {
cls = VmType.getPrimitiveClass('S');
} else if ("int".equals(name)) {
cls = VmType.getPrimitiveClass('I');
} else if ("float".equals(name)) {
cls = VmType.getPrimitiveClass('F');
} else if ("long".equals(name)) {
cls = VmType.getPrimitiveClass('J');
} else if ("double".equals(name)) {
cls = VmType.getPrimitiveClass('D');
} else {
throw new ClassNotFoundException(name
+ " is not a primitive type");
}
clsMgr.addLoadedClass(name, cls);
return cls;
} else {
return loadClass(name, true);
}
}
/**
* Load a VmClass with a given name
*
* @param name
* @param resolve
* @return The loaded class
* @throws ClassNotFoundException
*/
public final VmType loadClass(String name, boolean resolve)
throws ClassNotFoundException {
/*
* if (clsMgr == null) { clsMgr = new VmClassLoader(classesURL);
*/
return clsMgr.loadClass(name, resolve);
}
/**
* Compile the methods in the given class to native code.
*
* @param os
* @throws ClassNotFoundException
*/
private final void compileClasses(NativeStream os, VmArchitecture arch)
throws ClassNotFoundException {
final NativeCodeCompiler[] compilers = arch.getCompilers();
final int optLevel = compilers.length - 1;
// Use the most optimizing compiler here
final NativeCodeCompiler compiler = compilers[ optLevel];
int oldCount;
int newCount;
boolean again;
do {
again = false;
oldCount = clsMgr.getLoadedClassCount();
for (Iterator i = clsMgr.getLoadedClasses().iterator(); i.hasNext();) {
final VmType vmClass = (VmType) i.next();
vmClass.link();
final boolean compHigh = isCompileHighOptLevel(vmClass);
if (!vmClass.isCpRefsResolved() && compHigh) {
//log("Resolving CP of " + vmClass.getName(),
//Project.MSG_VERBOSE);
vmClass.resolveCpRefs(clsMgr);
again = true;
}
try {
final int mcnt;
final int startLength = os.getLength();
if (compHigh) {
log("Full Compile " + vmClass.getName(),
Project.MSG_VERBOSE);
mcnt = vmClass.compileBootstrap(compiler, os, optLevel);
totalHighMethods += mcnt;
totalHighMethodSize += (os.getLength() - startLength);
} else {
log("Min. Compile " + vmClass.getName(),
Project.MSG_VERBOSE);
mcnt = vmClass.compileBootstrap(compilers[ 0], os, 0);
totalLowMethods += mcnt;
totalLowMethodSize += (os.getLength() - startLength);
}
again |= (mcnt > 0);
} catch (Throwable ex) {
throw new BuildException("Compile of " + vmClass.getName()
+ " failed", ex);
}
if (!vmClass.isCompiled()) { throw new BuildException(
"Class should have been compiled by now"); }
}
newCount = clsMgr.getLoadedClassCount();
if (false) {
log("oldCount " + oldCount + ", newCount " + newCount,
Project.MSG_INFO);
}
} while ((oldCount != newCount) || again);
}
/**
* Should the given type be compiled with the best compiler.
*
* @param vmClass
* @return
*/
protected boolean isCompileHighOptLevel(VmType vmClass) {
if (vmClass.isArray()) { return true; }
final String name = vmClass.getName();
if (compileHighOptLevelPackages.contains(name)) { return true; }
final int lastDotIdx = name.lastIndexOf('.');
final String pkg = (lastDotIdx > 0) ? name.substring(0, lastDotIdx)
: "";
if (compileHighOptLevelPackages.contains(pkg)) { return true; }
return false;
}
/**
* Save the native stream to destFile.
*
* @param os
* @throws BuildException
*/
protected void storeImage(NativeStream os) throws BuildException {
try {
log("Creating image");
FileOutputStream fos = new FileOutputStream(destFile);
fos.write(os.getBytes(), 0, os.getLength());
fos.close();
} catch (IOException ex) {
throw new BuildException(ex);
}
}
protected void setupCompileHighOptLevelPackages() {
addCompileHighOptLevel("java.io");
addCompileHighOptLevel("java.lang");
addCompileHighOptLevel("java.lang.ref");
addCompileHighOptLevel("java.lang.reflect");
addCompileHighOptLevel("java.net");
addCompileHighOptLevel("java.util");
addCompileHighOptLevel("java.util.jar");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?