implement JavaClassLoader; ## Java Class Loader.# include "sys.m"; sys: Sys; stderr: ref Sys->FD; include "keyring.m"; kr: Keyring; include "string.m"; str: String; include "math.m"; math: Math; include "hash.m"; hash: Hash; include "loader.m";include "classloader.m"; ld: Loader; Niladt: import Loader; jassist: JavaAssist; jtrace: JavaTrace; JDEBUG, JVERBOSE: import JavaTrace; getint, getintarray, getptr: import jassist; getreloc, getrtreloc, getstring: import jassist; getclassadt, getabsint, getadtstring: import jassist; getbytearray, getstrarray, arrayof: import jassist; getmd, putclass, putint, putmod: import jassist; putobj, putptr, putstring, makeadt: import jassist; bytearraytoJS, intarraytoJS: import jassist; bigarraytoJS, realarraytoJS: import jassist; ArraytoJS, JStoObject: import jassist; this: JavaClassLoader;thisnil: Nilmod;sysnil: Nilmod;loadlinks: array of Loader->Link;syslinks: array of Loader->Link;relocs: list of ref Class;relocd: list of ref Class;interf: list of ref Class;interfx: list of ref Class;initcl: list of ref Class;main: ref Class;arrayclass: ref Class;arraymd: ref Loader->Niladt;stringclass: ref Class;fsindir: int;cur: string; interfaces: array of ref Class;ninterfaces: int = 0;linterfaces: int = 0; INITINTER: con 32; acqchan: chan of int;relchan: chan of int;exitchan: chan of int; MSHUTDOWN, MENTER, MEXIT, MWAIT, MNOTIFY, MSLEEP, MINTERRUPT, MTIMER, MSYNC: con iota; monitorctl: chan of (int, ref ThreadData, ref Object, int);threadctl: chan of (ref ThreadData, int); threadcount: int = 0;daemoncount: int = 0;stopped: int = 0; ident: con "ClassLoader";warn: int = 1;debug: int = 0;verbose: int = 0;errors: int = 0; # for generating ClassLoader exceptions use# the following con's. They will be turned# into a corresponding Java Exception by # sysexcetion# when thrown the format is:# raise( ex +":"+detail );# see loaderror();## NOTE: the "raise" string has limited size# hence the "e"+<int>#JCLDREX : con "JLD:"; #prefixnoclassdeffound,classcircularity,classformat,nosuchmethod,nosuchfield,unsatisfiedlink,linkageerr,exceptionininitializer : con "e" + (string iota); badcallindex : con "call index";nocloneindex : con "clone index"; encoding := array[] of{ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-',}; bits := array[] of { 16r80, 16r40, 16r20, 16r10, 16r08, 16r04, 16r02, 16r01 };mbits := array[] of { 16r80, 16r20, 16r08, 16r02 }; ## Diagnostics.# mesg(s: string){ sys->fprint(stderr, "%s: %s\n", ident, s);} diag(s: string){ if (cur != nil) s = cur + ": " + s; mesg(s); errors++;} loaderror( ex : string, msg : string ){ s := msg; # if prefix exists then just rethrow msg if ( str->prefix( JCLDREX+ex, msg ) == 0 ) { if ( cur != nil ) s = cur +": " + s; s = sys->sprint( "%s%s:%s", JCLDREX, ex, s ); } trace(JDEBUG,s); raise s;} error(s: string){ if ( s == nil ) s = JCLDREX + "fatal error"; else { # if prefix exists then just re-throw s if ( str->prefix(JCLDREX,s) == 0 ) { # add prefix to tag as a Loader ex s = sys->sprint( "%s%s:%s", JCLDREX, s, cur ); } } trace(JDEBUG,s); raise s;} warning(s: string){ if (!warn) return; if (cur != nil) s = cur + ": " + s; sys->fprint(stderr, "%s: warning: %s\n", ident, s);} trace(c: int, s: string){ if (jtrace != nil) jtrace->trace(c, s);} loadtrace(){ if (jtrace != nil) return; jtrace = load JavaTrace JavaTrace->PATH; if (jtrace == nil) error(sys->sprint("could not load %s: %r", JavaTrace->PATH)); jtrace->init(jassist);} ## Load synchronization. Allow only one thread to be loading at a time.# loadsync(){ for (;;) { alt { <- acqchan => ; <- exitchan => return; } alt { <- relchan => ; <- exitchan => return; } }} acquire(){ acqchan <-= 0;} release(){ relchan <-= 0;} context: ref Draw->Context; ## Initialize loader. Entry.#init(j: JavaClassLoader, ctxt: ref Draw->Context){ sys = load Sys Sys->PATH; stderr = sys->fildes(2); context = ctxt; kr = load Keyring Keyring->PATH; if (kr == nil) error(sys->sprint("could not load %s: %r", Keyring->PATH)); str = load String String->PATH; if (str == nil) error(sys->sprint("could not load %s: %r", String->PATH)); math = load Math Math->PATH; if (math == nil) error(sys->sprint("could not load %s: %r", Math->PATH)); math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX); hash = load Hash Hash->PATH; if (hash == nil) error(sys->sprint("could not load %s: %r", Hash->PATH)); ld = load Loader Loader->PATH; if (ld == nil) error(sys->sprint("could not load %s: %r", Loader->PATH)); jassist = load JavaAssist JavaAssist->PATH; if (jassist == nil) error(sys->sprint("could not load %s: %r", JavaAssist->PATH)); if (verbose) { loadtrace(); if (debug) jtrace->level = JDEBUG; else jtrace->level = JVERBOSE; } fsindir = jassist->little_endian(); this = j; thisnil = jassist->jclnilmod(j); sysnil = jassist->sysnilmod(sys); loadlinks = ld->link(thisnil); syslinks = ld->link(sysnil); if (loadlinks == nil || syslinks == nil) error(sys->sprint("Loader->link failed: %r")); initloadhash(); acqchan = chan of int; relchan = chan of int; exitchan = chan of int; spawn loadsync(); monitorctl = chan of (int, ref ThreadData, ref Object, int); spawn monitor(); threadctl = chan of (ref ThreadData, int); spawn threadmanager(); jniinit();} loadarrayclass(){ arrayclass = loader(ARRAYCLASS); arraymd = arrayclass.moddata;} loadstringclass(){ stringclass = loader(STRINGCLASS);} ## Native interface initialization.#jniinit(){ j := load JavaNative JavaNative->PATH; if (j == nil) error(sys->sprint("could not load %s: %r", JavaNative->PATH)); e := j->init(sys, ld, this, jassist); if (e != nil) error(sys->sprint("JavaNative->init failed: %s", e));} ## Shutdown loader. Entry.#shutdown(){ if (exitchan != nil) { exitchan <-= 0; exitchan = nil; } if (monitorctl != nil) { monitorctl <-= (MSHUTDOWN, nil, nil, 0); monitorctl = nil; } if (threadctl != nil) { threadctl <-= (nil, ThreadData.SHUTDOWN); threadctl = nil; }} ## Load a class and print information about it.# Does not resolve the class and should not be# called in the execution environment. Entry.#info(name: string){ c := getclass(name); if (c.state == NEW) c.loadclass(); loadtrace(); jtrace->info(c);} ## Perform outstanding relocation on loaded classes.#doreloc(){ # # Load classes we need for relocation. # while (relocs != nil) { r: list of ref Class; r = nil; reloc := hd relocs; relocs = tl relocs; trace(JDEBUG, sys->sprint("reloc %s", reloc.name)); i := CLASSREF; while ((s := getstring(reloc.mod, i)) != nil) { if (s != LOADER) r = loadhierarchy(s) :: r; else r = nil :: r; i += 2 * WORDZ; } reloc.refs = mkclarray(r); reloc.relocate(); relocd = reloc :: relocd; } # # Patch the module data of the relocated classes. # while (relocd != nil) { patch := hd relocd; relocd = tl relocd; trace(JDEBUG, sys->sprint("modpatch %s", patch.name)); patch.modpatch(); if (patch.native != nil || patch.classinit != nil) { initcl = patch :: initcl; patch.state = LOADED; } else patch.state = INITED; } # # Extend interfaces. # while (interfx != nil) { extend := hd interfx; interfx = tl interfx; extend.interdirect = extend.interextends; extend.extinterfaces(); } # # Make interface linkage tables for classes that implement interfaces. # while (interf != nil) { inter := hd interf; interf = tl interf; inter.interdirect = inter.interextends; inter.linkinterfaces(); } # # Call class initializers. # initc : ref Class; t : ref ThreadData; { while (initcl != nil) { initc = hd initcl; initcl = tl initcl; initc.state = INITED; trace(JVERBOSE, sys->sprint("Switching class %s state to INITED", initc.name)); t = getthreaddata(); release(); unblock(t); if (initc.native != nil) initc.initjni(); if (initc.classinit != nil) { trace(JVERBOSE, sys->sprint("%s-><clinit>()", initc.name)); jassist->mcall0(initc.mod, initc.classinit.value); trace(JDEBUG, sys->sprint("clinit done")); } block(t); acquire(); } } exception e { "*disabled" => #NOTE: a raise is only expected from the init calls therefore # when we reach here we need to block and acquire block(t); acquire(); trace(JVERBOSE, sys->sprint("Some exception: %s", e)); raise e; if ( str->prefix(JCLDREX+exceptionininitializer, e ) == 1 ) loaderror(exceptionininitializer, e ); #rethrow else { # clear any java exception; we are replacing it t.culprit = nil; loaderror(exceptionininitializer, sys->sprint("%s[unk]", initc.name)); } }} ## Main "load class" routine. Load a class hierarchy and# its dependencies and prepare it for use. Entry.# No return on error.#loader(name: string): ref Class{ released := 0; t := getthreaddata(); { trace(JDEBUG, sys->sprint("load class %s", name)); block(t); acquire(); c := loadhierarchy(name); if (relocs != nil) doreloc(); release(); unblock(t); released = 1; trace(JDEBUG, sys->sprint("loader() exit"));# if (errors)# error(nil); return c; } exception e { "*disabled" => if(released == 0) { release(); unblock(t); } if (e == nil) e = "exit"; if ( str->prefix(JCLDREX, e) == 1 ) error(e); error( sys->sprint( "%s", e) ); #else if (e.name == noclassdeffound) #{ # error(nil); #} #else # error(sys->sprint("loader exception: %s: %s: %d", e.mod, e.name, e.pc)); } return nil;Lines 1–500 of 3541. Load more
implement JavaClassLoader; # # Java Class Loader. # include "sys.m"; sys: Sys; stderr: ref Sys->FD; include "keyring.m"; kr: Keyring; include "string.m"; str: String; include "math.m"; math: Math; include "hash.m"; hash: Hash; include "loader.m"; include "classloader.m"; ld: Loader; Niladt: import Loader; jassist: JavaAssist; jtrace: JavaTrace; JDEBUG, JVERBOSE: import JavaTrace; getint, getintarray, getptr: import jassist; getreloc, getrtreloc, getstring: import jassist; getclassadt, getabsint, getadtstring: import jassist; getbytearray, getstrarray, arrayof: import jassist; getmd, putclass, putint, putmod: import jassist; putobj, putptr, putstring, makeadt: import jassist; bytearraytoJS, intarraytoJS: import jassist; bigarraytoJS, realarraytoJS: import jassist; ArraytoJS, JStoObject: import jassist; this: JavaClassLoader; thisnil: Nilmod; sysnil: Nilmod; loadlinks: array of Loader->Link; syslinks: array of Loader->Link; relocs: list of ref Class; relocd: list of ref Class; interf: list of ref Class; interfx: list of ref Class; initcl: list of ref Class; main: ref Class; arrayclass: ref Class; arraymd: ref Loader->Niladt; stringclass: ref Class; fsindir: int; cur: string; interfaces: array of ref Class; ninterfaces: int = 0; linterfaces: int = 0; INITINTER: con 32; acqchan: chan of int; relchan: chan of int; exitchan: chan of int; MSHUTDOWN, MENTER, MEXIT, MWAIT, MNOTIFY, MSLEEP, MINTERRUPT, MTIMER, MSYNC: con iota; monitorctl: chan of (int, ref ThreadData, ref Object, int); threadctl: chan of (ref ThreadData, int); threadcount: int = 0; daemoncount: int = 0; stopped: int = 0; ident: con "ClassLoader"; warn: int = 1; debug: int = 0; verbose: int = 0; errors: int = 0; # for generating ClassLoader exceptions use # the following con's. They will be turned # into a corresponding Java Exception by # sysexcetion # when thrown the format is: # raise( ex +":"+detail ); # see loaderror(); # # NOTE: the "raise" string has limited size # hence the "e"+<int> # JCLDREX : con "JLD:"; #prefix noclassdeffound, classcircularity, classformat, nosuchmethod, nosuchfield, unsatisfiedlink, linkageerr, exceptionininitializer : con "e" + (string iota); badcallindex : con "call index"; nocloneindex : con "clone index"; encoding := array[] of { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', }; bits := array[] of { 16r80, 16r40, 16r20, 16r10, 16r08, 16r04, 16r02, 16r01 }; mbits := array[] of { 16r80, 16r20, 16r08, 16r02 }; # # Diagnostics. # mesg(s: string) { sys->fprint(stderr, "%s: %s\n", ident, s); } diag(s: string) { if (cur != nil) s = cur + ": " + s; mesg(s); errors++; } loaderror( ex : string, msg : string ) { s := msg; # if prefix exists then just rethrow msg if ( str->prefix( JCLDREX+ex, msg ) == 0 ) { if ( cur != nil ) s = cur +": " + s; s = sys->sprint( "%s%s:%s", JCLDREX, ex, s ); } trace(JDEBUG,s); raise s; } error(s: string) { if ( s == nil ) s = JCLDREX + "fatal error"; else { # if prefix exists then just re-throw s if ( str->prefix(JCLDREX,s) == 0 ) { # add prefix to tag as a Loader ex s = sys->sprint( "%s%s:%s", JCLDREX, s, cur ); } } trace(JDEBUG,s); raise s; } warning(s: string) { if (!warn) return; if (cur != nil) s = cur + ": " + s; sys->fprint(stderr, "%s: warning: %s\n", ident, s); } trace(c: int, s: string) { if (jtrace != nil) jtrace->trace(c, s); } loadtrace() { if (jtrace != nil) return; jtrace = load JavaTrace JavaTrace->PATH; if (jtrace == nil) error(sys->sprint("could not load %s: %r", JavaTrace->PATH)); jtrace->init(jassist); } # # Load synchronization. Allow only one thread to be loading at a time. # loadsync() { for (;;) { alt { <- acqchan => ; <- exitchan => return; } alt { <- relchan => ; <- exitchan => return; } } } acquire() { acqchan <-= 0; } release() { relchan <-= 0; } context: ref Draw->Context; # # Initialize loader. Entry. # init(j: JavaClassLoader, ctxt: ref Draw->Context) { sys = load Sys Sys->PATH; stderr = sys->fildes(2); context = ctxt; kr = load Keyring Keyring->PATH; if (kr == nil) error(sys->sprint("could not load %s: %r", Keyring->PATH)); str = load String String->PATH; if (str == nil) error(sys->sprint("could not load %s: %r", String->PATH)); math = load Math Math->PATH; if (math == nil) error(sys->sprint("could not load %s: %r", Math->PATH)); math->FPcontrol(0, Math->INVAL|Math->ZDIV|Math->OVFL|Math->UNFL|Math->INEX); hash = load Hash Hash->PATH; if (hash == nil) error(sys->sprint("could not load %s: %r", Hash->PATH)); ld = load Loader Loader->PATH; if (ld == nil) error(sys->sprint("could not load %s: %r", Loader->PATH)); jassist = load JavaAssist JavaAssist->PATH; if (jassist == nil) error(sys->sprint("could not load %s: %r", JavaAssist->PATH)); if (verbose) { loadtrace(); if (debug) jtrace->level = JDEBUG; else jtrace->level = JVERBOSE; } fsindir = jassist->little_endian(); this = j; thisnil = jassist->jclnilmod(j); sysnil = jassist->sysnilmod(sys); loadlinks = ld->link(thisnil); syslinks = ld->link(sysnil); if (loadlinks == nil || syslinks == nil) error(sys->sprint("Loader->link failed: %r")); initloadhash(); acqchan = chan of int; relchan = chan of int; exitchan = chan of int; spawn loadsync(); monitorctl = chan of (int, ref ThreadData, ref Object, int); spawn monitor(); threadctl = chan of (ref ThreadData, int); spawn threadmanager(); jniinit(); } loadarrayclass() { arrayclass = loader(ARRAYCLASS); arraymd = arrayclass.moddata; } loadstringclass() { stringclass = loader(STRINGCLASS); } # # Native interface initialization. # jniinit() { j := load JavaNative JavaNative->PATH; if (j == nil) error(sys->sprint("could not load %s: %r", JavaNative->PATH)); e := j->init(sys, ld, this, jassist); if (e != nil) error(sys->sprint("JavaNative->init failed: %s", e)); } # # Shutdown loader. Entry. # shutdown() { if (exitchan != nil) { exitchan <-= 0; exitchan = nil; } if (monitorctl != nil) { monitorctl <-= (MSHUTDOWN, nil, nil, 0); monitorctl = nil; } if (threadctl != nil) { threadctl <-= (nil, ThreadData.SHUTDOWN); threadctl = nil; } } # # Load a class and print information about it. # Does not resolve the class and should not be # called in the execution environment. Entry. # info(name: string) { c := getclass(name); if (c.state == NEW) c.loadclass(); loadtrace(); jtrace->info(c); } # # Perform outstanding relocation on loaded classes. # doreloc() { # # Load classes we need for relocation. # while (relocs != nil) { r: list of ref Class; r = nil; reloc := hd relocs; relocs = tl relocs; trace(JDEBUG, sys->sprint("reloc %s", reloc.name)); i := CLASSREF; while ((s := getstring(reloc.mod, i)) != nil) { if (s != LOADER) r = loadhierarchy(s) :: r; else r = nil :: r; i += 2 * WORDZ; } reloc.refs = mkclarray(r); reloc.relocate(); relocd = reloc :: relocd; } # # Patch the module data of the relocated classes. # while (relocd != nil) { patch := hd relocd; relocd = tl relocd; trace(JDEBUG, sys->sprint("modpatch %s", patch.name)); patch.modpatch(); if (patch.native != nil || patch.classinit != nil) { initcl = patch :: initcl; patch.state = LOADED; } else patch.state = INITED; } # # Extend interfaces. # while (interfx != nil) { extend := hd interfx; interfx = tl interfx; extend.interdirect = extend.interextends; extend.extinterfaces(); } # # Make interface linkage tables for classes that implement interfaces. # while (interf != nil) { inter := hd interf; interf = tl interf; inter.interdirect = inter.interextends; inter.linkinterfaces(); } # # Call class initializers. # initc : ref Class; t : ref ThreadData; { while (initcl != nil) { initc = hd initcl; initcl = tl initcl; initc.state = INITED; trace(JVERBOSE, sys->sprint("Switching class %s state to INITED", initc.name)); t = getthreaddata(); release(); unblock(t); if (initc.native != nil) initc.initjni(); if (initc.classinit != nil) { trace(JVERBOSE, sys->sprint("%s-><clinit>()", initc.name)); jassist->mcall0(initc.mod, initc.classinit.value); trace(JDEBUG, sys->sprint("clinit done")); } block(t); acquire(); } } exception e { "*disabled" => #NOTE: a raise is only expected from the init calls therefore # when we reach here we need to block and acquire block(t); acquire(); trace(JVERBOSE, sys->sprint("Some exception: %s", e)); raise e; if ( str->prefix(JCLDREX+exceptionininitializer, e ) == 1 ) loaderror(exceptionininitializer, e ); #rethrow else { # clear any java exception; we are replacing it t.culprit = nil; loaderror(exceptionininitializer, sys->sprint("%s[unk]", initc.name)); } } } # # Main "load class" routine. Load a class hierarchy and # its dependencies and prepare it for use. Entry. # No return on error. # loader(name: string): ref Class { released := 0; t := getthreaddata(); { trace(JDEBUG, sys->sprint("load class %s", name)); block(t); acquire(); c := loadhierarchy(name); if (relocs != nil) doreloc(); release(); unblock(t); released = 1; trace(JDEBUG, sys->sprint("loader() exit")); # if (errors) # error(nil); return c; } exception e { "*disabled" => if(released == 0) { release(); unblock(t); } if (e == nil) e = "exit"; if ( str->prefix(JCLDREX, e) == 1 ) error(e); error( sys->sprint( "%s", e) ); #else if (e.name == noclassdeffound) #{ # error(nil); #} #else # error(sys->sprint("loader exception: %s: %s: %d", e.mod, e.name, e.pc)); } return nil;