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 + -
显示快捷键?