From 0a5b82f6d3625f280f22f5b5a53234efd0b02a0c Mon Sep 17 00:00:00 2001 From: platypusguy <920630+platypusguy@users.noreply.github.com> Date: Fri, 4 Feb 2022 00:41:53 -0800 Subject: [PATCH] JACOBIN-154 Added a large subset of Java libraries to be preloaded. Rather than using a list, Jacobin loads the entire directory (which include java.lang., etc.) --- src/classloader/classloader.go | 67 +++++++++++++++++++++++----------- src/instantiate.go | 12 +++--- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/classloader/classloader.go b/src/classloader/classloader.go index d4d13e4c..ea48dda3 100644 --- a/src/classloader/classloader.go +++ b/src/classloader/classloader.go @@ -7,11 +7,11 @@ package classloader import ( - "bufio" "bytes" "encoding/gob" "errors" "fmt" + "io/fs" "jacobin/globals" "jacobin/log" "jacobin/util" @@ -176,32 +176,55 @@ func cfe(msg string) error { return errors.New(errMsg) } -// LoadBaseClasses loads a basic set of classes that are specified in the file -// classes\baseclasslist.txt, which is found in JACOBIN_HOME. It's similar to -// classlist file in the JDK, except shorter (for the nonce) +// // LoadBaseClasses loads a basic set of classes that are specified in the file +// // classes\baseclasslist.txt, which is found in JACOBIN_HOME. It's similar to +// // classlist file in the JDK, except shorter (for the nonce) +// func LoadBaseClasses(global *globals.Globals) { +// classList := global.JacobinHome + "classes" + string(os.PathSeparator) + "baseclasslist.txt" +// classList = util.ConvertToPlatformPathSeparators(classList) +// file, err := os.Open(classList) +// if err != nil { +// _ = log.Log("Did not find baseclasslist.txt in JACOBIN_HOME ("+classList+")", log.WARNING) +// _ = file.Close() +// } else { +// defer file.Close() +// +// scanner := bufio.NewScanner(file) +// for scanner.Scan() { +// rawName := scanner.Text() +// fileName := util.ConvertInternalClassNameToFilename(rawName) +// name := util.ConvertToPlatformPathSeparators( +// globals.JacobinHome() + "classes" + string(os.PathSeparator) + fileName) +// _, _ = LoadClassFromFile(BootstrapCL, name) +// // LoadReferencedClasses(BootstrapCL, rawName) +// } +// err = nil // used only to be able to add a breakpoint in debugger. +// } +// } + func LoadBaseClasses(global *globals.Globals) { - classList := global.JacobinHome + "classes" + string(os.PathSeparator) + "baseclasslist.txt" - classList = util.ConvertToPlatformPathSeparators(classList) - file, err := os.Open(classList) + if len(global.JacobinHome) == 0 { + _ = log.Log("JACOBIN_HOME not specified. Program may fail.", log.WARNING) + } + + err := filepath.WalkDir(globals.JacobinHome()+"classes", walk) + // LoadClassFromFile(BootstrapCL, walk) if err != nil { - _ = log.Log("Did not find baseclasslist.txt in JACOBIN_HOME ("+classList+")", log.WARNING) - _ = file.Close() - } else { - defer file.Close() - - scanner := bufio.NewScanner(file) - for scanner.Scan() { - rawName := scanner.Text() - fileName := util.ConvertInternalClassNameToFilename(rawName) - name := util.ConvertToPlatformPathSeparators( - globals.JacobinHome() + "classes" + string(os.PathSeparator) + fileName) - _, _ = LoadClassFromFile(BootstrapCL, name) - // LoadReferencedClasses(BootstrapCL, rawName) - } - err = nil // used only to be able to add a breakpoint in debugger. + fmt.Fprintf(os.Stderr, "Error in filepath.Walkdir: %s", err.Error()) } } +func walk(s string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + LoadClassFromFile(BootstrapCL, s) + // println(s) + } + return nil +} + // LoadReferencedClasses loads the classes referenced in the loading of the class named clName. // It does this by reading the class entries (7) in the CP and sending the class names it finds // there to a go channel that will load the class. diff --git a/src/instantiate.go b/src/instantiate.go index c4e24d4f..dd7ce522 100644 --- a/src/instantiate.go +++ b/src/instantiate.go @@ -16,9 +16,9 @@ import ( func instantiateClass(classname string) (interface{}, error) { log.Log("Instantiating class: "+classname, log.FINEST) recheck: - k, present := classloader.Classes[classname] - if k.Status == 'I' { // the class is being loaded - goto recheck // recheck the status until it changes (i.e., the class is loaded) + k, present := classloader.Classes[classname] // TODO: Put a mutex around this the same one used for writing. + if k.Status == 'I' { // the class is being loaded + goto recheck // recheck the status until it changes (i.e., until the class is loaded) } else if !present { // the class has not yet been loaded if classloader.LoadClassFromNameOnly(classname) != nil { log.Log("Error loading class: "+classname+". Exiting.", log.SEVERE) @@ -30,13 +30,13 @@ recheck: if len(k.Data.Fields) > 0 { for i := 0; i < len(k.Data.Fields); i++ { f := k.Data.Fields[i] - initializeField(f, &k.Data.CP) + initializeField(f, &k.Data.CP, classname) } } return nil, nil } -func initializeField(f classloader.Field, cp *classloader.CPool) { +func initializeField(f classloader.Field, cp *classloader.CPool, cn string) { name := cp.Utf8Refs[int(f.Name)] desc := cp.Utf8Refs[int(f.Desc)] var attr string = "" @@ -52,7 +52,7 @@ func initializeField(f classloader.Field, cp *classloader.CPool) { } } } - fmt.Fprintf(os.Stdout, "Field to initialize: %s, type: %s\n", name, desc) + fmt.Fprintf(os.Stdout, "Class: %s, Field to initialize: %s, type: %s\n", cn, name, desc) if attr != "" { fmt.Fprintf(os.Stdout, "Attribute name: %s\n", attr) }