abstractbootimagebuilder.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 1,109 行 · 第 1/3 页

JAVA
1,109
字号
/**
 * $Id: AbstractBootImageBuilder.java,v 1.23 2004/02/26 10:33:12 epr Exp $
 */

package org.jnode.build;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import org.apache.tools.ant.Project;
import org.jnode.assembler.Label;
import org.jnode.assembler.NativeStream;
import org.jnode.assembler.UnresolvedObjectRefException;
import org.jnode.assembler.x86.X86Stream;
import org.jnode.plugin.PluginException;
import org.jnode.plugin.PluginRegistry;
import org.jnode.plugin.model.PluginRegistryModel;
import org.jnode.util.NumberUtils;
import org.jnode.vm.HeapHelperImpl;
import org.jnode.vm.Unsafe;
import org.jnode.vm.Vm;
import org.jnode.vm.VmArchitecture;
import org.jnode.vm.VmProcessor;
import org.jnode.vm.VmSystemClassLoader;
import org.jnode.vm.VmSystemObject;
import org.jnode.vm.bytecode.BytecodeParser;
import org.jnode.vm.classmgr.ObjectLayout;
import org.jnode.vm.classmgr.VmArray;
import org.jnode.vm.classmgr.VmClassType;
import org.jnode.vm.classmgr.VmMethodCode;
import org.jnode.vm.classmgr.VmStatics;
import org.jnode.vm.classmgr.VmType;
import org.jnode.vm.compiler.NativeCodeCompiler;
import org.jnode.vm.memmgr.HeapHelper;
import org.jnode.vm.memmgr.VmHeapManager;
import org.jnode.vm.memmgr.def.DefaultHeapManager;
import org.jnode.vm.memmgr.def.VmBootHeap;
import org.jnode.vm.memmgr.def.VmDefaultHeap;

/**
 * Build the boot image from an assembler compiled bootstrap (in ELF format)
 * combined with the precompiled Java classes.
 */
public abstract class AbstractBootImageBuilder extends AbstractPluginsTask {

    /** System property set to indicate build time */
    public static final String BUILDTIME_PROPERTY = "org.jnode.buildtime";

    /**
     * Classname/packagename of those classes/packages that need highly
     * optimized compilation
     */
    private final HashSet compileHighOptLevelPackages = new HashSet();

    private File destFile;

    private File kernelFile;

    private File listFile;

    private File debugFile;

    private File jarFile;
    
    private String version;

    private VmSystemClassLoader clsMgr;

    private URL classesURL = null;

    private Set legalInstanceClasses;

    /** Set of jbects that should not yet be emitted */
    private final Set blockedObjects = new HashSet();

    protected boolean debug = false;

    protected static final Label bootHeapStart = new Label("$$bootHeapStart");

    protected static final Label bootHeapEnd = new Label("$$bootHeapEnd");

    protected static final Label imageEnd = new Label("$$image_end");

    protected static final Label initialStack = new Label("$$initialStack");

    protected static final Label initialStackPtr = new Label(
            "$$initialStackPtr");

    private int totalHighMethodSize;

    private int totalHighMethods;

    private int totalLowMethodSize;

    private int totalLowMethods;

    /**
     * Construct a new BootImageBuilder
     */
    public AbstractBootImageBuilder() {
        setupCompileHighOptLevelPackages();
        legalInstanceClasses = setupLegalInstanceClasses();
    }

    public final void execute() throws BuildException {
        // Create the image
        doExecute();
        // Remove all garbage objects
        cleanup();
        System.gc();
        // Make sure that all finalizers are called, in order to remove tmp files.
        Runtime.getRuntime().runFinalization();
    }
    
    private final void doExecute() throws BuildException {
        debug = (getProject().getProperty("jnode.debug") != null);

        final long lmJar = jarFile.lastModified();
        final long lmKernel = kernelFile.lastModified();
        final long lmDest = destFile.lastModified();
        final long lmPIL = getPluginListFile().lastModified();

        if (version == null) {
            throw new BuildException("Version property must be set");
        }
        
        final PluginList piList;
        final long lmPI;
        try {
            log("plugin-list: " + getPluginListFile(), Project.MSG_DEBUG);
            piList = getPluginList();
            lmPI = piList.lastModified();
        } catch (PluginException ex) {
            throw new BuildException(ex);
        } catch (IOException ex) {
            throw new BuildException(ex);
        }

        if ((lmJar < lmDest) && (lmKernel < lmDest) && (lmPIL < lmDest)
                && (lmPI < lmDest)) { 
        // No need to do anything, skip
        return; }

        if (debugFile != null) {
            debugFile.delete();
        }

        try {
            System.getProperties().setProperty(BUILDTIME_PROPERTY, "1");

            // Load the plugin descriptors
            final PluginRegistry piRegistry;
            piRegistry = new PluginRegistryModel(piList.getPluginList());
            //piRegistry = new
            // PluginRegistryModel(piList.getDescriptorUrlList());
            testPluginPrerequisites(piRegistry);

            /* Now create the processor */
            final VmArchitecture arch = getArchitecture();
            final NativeStream os = createNativeStream();
            clsMgr = new VmSystemClassLoader(classesURL, arch,
                    new BuildObjectResolver(os, this));
            blockedObjects.add(clsMgr);
            blockedObjects.add(clsMgr.getStatics());
            blockedObjects.add(clsMgr.getStatics().getTable());

            if (debug) {
                log("Building in DEBUG mode", Project.MSG_WARN);
            }

            // Create the VM
            final HeapHelper helper = new HeapHelperImpl(arch);
            final Vm vm = new Vm(version, arch, new DefaultHeapManager(clsMgr, helper,
                    clsMgr.getStatics()), clsMgr.getStatics(), debug);
            blockedObjects.add(vm);

            final VmProcessor proc = createProcessor(clsMgr.getStatics());
            log("Building for " + proc.getCPUID());

            final Label clInitCaller = new Label("$$clInitCaller");
            VmType systemClasses[] = VmType.initializeForBootImage(clsMgr);
            for (int i = 0; i < systemClasses.length; i++) {
                clsMgr.addLoadedClass(systemClasses[ i].getName(),
                        systemClasses[ i]);
            }

            // First copy the native kernel file
            copyKernel(os);
            os.setObjectRef(bootHeapStart);

            // Setup a call to our first java method
            initImageHeader(os, clInitCaller, vm, piRegistry);

            // Create the initial stack
            createInitialStack(os, initialStack, initialStackPtr);

            /* Now load the classes */
            loadClass(VmMethodCode.class);
            loadClass(Unsafe.class);
            loadClass(VmSystemClassLoader.class);
            loadClass(VmType[].class);
            loadClass(Vm.class);
            loadClass(VmBootHeap.class);
            loadClass(VmDefaultHeap.class);
            loadClass(VmHeapManager.class);
            loadClass(VmStatics.class);
            loadClass(vm.getHeapManager().getClass());
            loadClass(HeapHelper.class);
            loadClass(HeapHelperImpl.class);

            loadSystemClasses();

            /* Now emit the processor */
            os.getObjectRef(proc);

            /* Let the compilers load its native symbol offsets */
            final NativeCodeCompiler[] cmps = arch.getCompilers();
            for (int i = 0; i < cmps.length; i++) {
                final NativeCodeCompiler cmp = cmps[ i];
                cmp.initialize(clsMgr);
                os.getObjectRef(cmp);
            }

            // Load the jarfile as byte-array
            copyJarFile(os);

            // Now emit all object images to the actual image
            emitObjects(os, arch, blockedObjects);

            // Disallow the loading of new classes
            clsMgr.setFailOnNewLoad(true);
            emitObjects(os, arch, blockedObjects);

            // Emit the classmanager
            log("Emit vm", Project.MSG_VERBOSE);
            blockedObjects.remove(vm);
            emitObjects(os, arch, blockedObjects);
            // Twice, this is intended!
            emitObjects(os, arch, blockedObjects);

            /* Set the bootclasses */
            log("prepare bootClassArray", Project.MSG_VERBOSE);
            final VmType bootClasses[] = clsMgr.prepareAfterBootstrap();
            os.getObjectRef(bootClasses);
            emitObjects(os, arch, blockedObjects);
            // Twice, this is intended!
            emitObjects(os, arch, blockedObjects);

            // Emit the classmanager
            log("Emit clsMgr", Project.MSG_VERBOSE);
            // Turn auto-compilation on
            clsMgr.setCompileRequired();
            blockedObjects.remove(clsMgr);
            emitObjects(os, arch, blockedObjects);
            // Twice, this is intended!
            emitObjects(os, arch, blockedObjects);

            // Emit the classmanager
            log("Emit statics", Project.MSG_VERBOSE);
            blockedObjects.remove(clsMgr.getStatics());
            emitObjects(os, arch, blockedObjects);
            // Twice, this is intended!
            emitObjects(os, arch, blockedObjects);

            // Emit the remaining objects
            log("Emit rest; blocked=" + blockedObjects, Project.MSG_VERBOSE);
            emitObjects(os, arch, null);
            log("statics table 0x"
                    + NumberUtils.hex(os.getObjectRef(
                            clsMgr.getStatics().getTable()).getOffset()),
                    Project.MSG_VERBOSE);

            /* Write static initializer code */
            emitStaticInitializerCalls(os, bootClasses, clInitCaller);

            // This is the end of the image
            X86Stream.ObjectInfo dummyObjectAtEnd = os
                    .startObject(loadClass(VmMethodCode.class));
            pageAlign(os);
            dummyObjectAtEnd.markEnd();
            os.setObjectRef(imageEnd);
            os.setObjectRef(bootHeapEnd);

            /* Link all native symbols */
            linkNativeSymbols(os);

            // Patch multiboot header
            patchHeader(os);

            // Store the image
            storeImage(os);

            // Generate the listfile
            printLabels(os, bootClasses, clsMgr.getStatics());

            // Generate debug info
            for (int i = 0; i < cmps.length; i++) {
                cmps[ i].dumpStatistics();
            }
            final int bootHeapSize = os.getObjectRef(bootHeapEnd).getOffset()
                    - os.getObjectRef(bootHeapStart).getOffset();
            final int bootHeapBitmapSize = (bootHeapSize / ObjectLayout.OBJECT_ALIGN) >> 3;
            log("Boot heap size " + (bootHeapSize >>> 10) + "K bitmap size "
                    + (bootHeapBitmapSize >>> 10) + "K");
            clsMgr.getStatics().dumpStatistics(System.out);

            logStatistics(os);

            BytecodeParser.dumpStatistics();
            
            log("Optimized methods     : " + totalHighMethods + ", avg size "
                    + (totalHighMethodSize / totalHighMethods) + ", tot size "
                    + totalHighMethodSize);
            log("Ondemand comp. methods: " + totalLowMethods + ", avg size "
                    + (totalLowMethodSize / totalLowMethods) + ", tot size "
                    + totalLowMethodSize);
            
            log("Done.");
            
            os.clear();
        } catch (Throwable ex) {
            ex.printStackTrace();
            throw new BuildException(ex);
        }
        
    }

    /**
     * Create a platform specific native stream.
     * 
     * @return NativeStream
     */
    protected abstract NativeStream createNativeStream();

    /**
     * Create the default processor for this architecture.
     * 
     * @return The processor
     * @throws BuildException
     */
    protected abstract VmProcessor createProcessor(VmStatics statics)
            throws BuildException;

    /**
     * Gets the target architecture.
     * 
     * @return The target architecture
     * @throws BuildException
     */
    protected abstract VmArchitecture getArchitecture() throws BuildException;

    /**
     * Copy the kernel native code into the native stream.
     * 

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?