Skip to content

Commit 47a7cb8

Browse files
author
zhourenjian
committed
Java2Script is now supporting Java-like hotspot loading.
1 parent 73c551c commit 47a7cb8

File tree

3 files changed

+255
-8
lines changed

3 files changed

+255
-8
lines changed

sources/net.sf.j2s.java.core/src/java/lang/Class.js

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,9 @@ Clazz.inheritArgs = new Clazz.args4InheritClass ();
276276
Clazz.inheritClass = function (clazzThis, clazzSuper, objSuper) {
277277
//var thisClassName = Clazz.getClassName (clazzThis);
278278
Clazz.extendsProperties (clazzThis, clazzSuper);
279-
if (objSuper != null) {
279+
if (Clazz.isClassUnloaded (clazzThis)) {
280+
// Don't change clazzThis.protoype! Keep it!
281+
} else if (objSuper != null) {
280282
// ! Unsafe of refrence prototype to an instance!
281283
// Feb 19, 2006 --josson
282284
// OK for this refrence to an instance, as this is anonymous instance,
@@ -1114,18 +1116,14 @@ Clazz.defineMethod = function (clazzThis, funName, funBody, funParams) {
11141116
* wrapping into deep hierarchies!
11151117
*/
11161118
var f$ = clazzThis.prototype[funName];
1117-
if (f$ == null) {
1118-
//*
1119+
if (f$ == null || (f$.claxxOwner == clazzThis
1120+
&& f$.funParams == fpName)) {
11191121
// property "funParams" will be used as a mark of only-one method
11201122
funBody.funParams = fpName;
11211123
funBody.claxxOwner = clazzThis;
11221124
clazzThis.prototype[funName] = funBody;
11231125
funBody.exClazz = clazzThis; // make it traceable
11241126
return funBody;
1125-
// */
1126-
} else if (f$.claxxOwner == clazzThis
1127-
&& f$.funParams == fpName) {
1128-
return f$;
11291127
}
11301128
var oldFun = null;
11311129
var oldStacks = new Array ();
@@ -1266,6 +1264,15 @@ Clazz.allClasses = new Object ();
12661264
Clazz.lastPackageName = null;
12671265
Clazz.lastPackage = null;
12681266

1267+
/* protected */
1268+
Clazz.unloadedClasses = new Array ();
1269+
1270+
/* public */
1271+
Clazz.isClassUnloaded = function (clzz) {
1272+
var thisClassName = Clazz.getClassName (clzz, true);
1273+
return Clazz.unloadedClasses[thisClassName] != null;
1274+
};
1275+
12691276
/* public */
12701277
Clazz.declarePackage = function (pkgName) {
12711278
if (Clazz.lastPackageName == pkgName) {
@@ -1348,6 +1355,10 @@ Clazz.evalType = function (typeStr, isQualified) {
13481355
*/
13491356
/* public */
13501357
Clazz.defineType = function (qClazzName, clazzFun, clazzParent, interfacez) {
1358+
var cf = Clazz.unloadedClasses[qClazzName];
1359+
if (cf != null) {
1360+
clazzFun = cf;
1361+
}
13511362
var idx = qClazzName.lastIndexOf (".");
13521363
if (idx != -1) {
13531364
var pkgName = qClazzName.substring (0, idx);
@@ -1618,6 +1629,10 @@ Clazz.declareInterface = function (prefix, name, interfacez) {
16181629
#-*/
16191630
Clazz.decorateAsClass = function (clazzFun, prefix, name, clazzParent,
16201631
interfacez, parentClazzInstance) {
1632+
var cf = Clazz.unloadedClasses[prefix.__PKG_NAME__ + "." + name];
1633+
if (cf != null) {
1634+
clazzFun = cf;
1635+
}
16211636
var qName = null;
16221637
Clazz.decorateFunction (clazzFun, prefix, name);
16231638
if (parentClazzInstance != null) {

sources/net.sf.j2s.java.core/src/java/lang/ClassExt.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,3 +811,57 @@ Clazz.forName = function (clazzName) {
811811
}
812812
};
813813

814+
/* For hotspot and unloading */
815+
816+
Clazz.unloadClass = function (qClazzName) {
817+
var cc = Clazz.evalType (qClazzName);
818+
if (cc != null) {
819+
Clazz.unloadedClasses[qClazzName] = cc;
820+
var clazzName = qClazzName;
821+
var pkgFrags = clazzName.split (/\./);
822+
var pkg = null;
823+
for (var i = 0; i < pkgFrags.length - 1; i++) {
824+
if (pkg == null) {
825+
pkg = Clazz.allPackage[pkgFrags[0]];
826+
} else {
827+
pkg = pkg[pkgFrags[i]]
828+
}
829+
}
830+
if (pkg == null) {
831+
Clazz.allPackage[pkgFrags[0]] = null;
832+
window[pkgFrags[0]] = null;
833+
// also try to unload inner or anonymous classes
834+
for (var c in window) {
835+
if (c.indexOf (qClazzName + "$") == 0) {
836+
window[c] = null;
837+
}
838+
}
839+
} else {
840+
pkg[pkgFrags[pkgFrags.length - 1]] = null;
841+
// also try to unload inner or anonymous classes
842+
for (var c in pkg) {
843+
if (c.indexOf (pkgFrags[pkgFrags.length - 1] + "$") == 0) {
844+
pkg[c] = null;
845+
}
846+
}
847+
}
848+
849+
if (Clazz.allClasses[qClazzName] == true) {
850+
Clazz.allClasses[qClazzName] = false;
851+
// also try to unload inner or anonymous classes
852+
for (var c in Clazz.allClasses) {
853+
if (c.indexOf (qClazzName + "$") == 0) {
854+
Clazz.allClasses[c] = false;
855+
}
856+
}
857+
}
858+
859+
if (window["ClazzLoader"] != null) {
860+
ClazzLoader.unloadClassExt (qClazzName);
861+
}
862+
863+
return true;
864+
}
865+
return false;
866+
};
867+

sources/net.sf.j2s.java.core/src/java/lang/ClassLoader.js

Lines changed: 179 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2166,7 +2166,13 @@ ClazzLoader.loadClass = function (name, optionalsLoaded, forced, async) {
21662166
&& !ClazzLoader.isClassExcluded (name)) {
21672167
var path = ClazzLoader.getClasspathFor (name/*, true*/);
21682168
if (!ClazzLoader.loadedScripts[path]) {
2169-
var n = new ClazzNode ();
2169+
var n = null;
2170+
if (Clazz.unloadedClasses[name] != null) {
2171+
n = ClazzLoader.findClass (name);
2172+
}
2173+
if (n == null) {
2174+
n = new ClazzNode ();
2175+
}
21702176
n.name = name;
21712177
n.path = path;
21722178
ClazzLoader.mappingPathNameNode (path, name, n);
@@ -2423,6 +2429,174 @@ ClazzLoader.destroyClassNode = function (node) {
24232429
}
24242430
};
24252431

2432+
/* For hotspot and unloading */
2433+
2434+
/* protected */
2435+
ClazzLoader.unloadClassExt = function (qClazzName) {
2436+
if (ClazzLoader.definedClasses != null) {
2437+
ClazzLoader.definedClasses[qClazzName] = false;
2438+
}
2439+
if (ClazzLoader.classpathMap["#" + qClazzName] != null) {
2440+
var pp = ClazzLoader.classpathMap["#" + qClazzName];
2441+
ClazzLoader.classpathMap["#" + qClazzName] = null;
2442+
var arr = ClazzLoader.classpathMap["$" + pp];
2443+
var removed = false;
2444+
for (var i = 0; i < arr.length; i++) {
2445+
if (arr[i] == qClazzName) {
2446+
for (var j = i; j < arr.length - 1; j++) {
2447+
arr[j] = arr[j + 1];
2448+
}
2449+
arr.length--;
2450+
removed = true;
2451+
break;
2452+
}
2453+
}
2454+
if (removed) {
2455+
ClazzLoader.classpathMap["$" + pp] = arr;
2456+
}
2457+
}
2458+
var n = ClazzLoader.findClass (qClazzName);
2459+
if (n != null) {
2460+
n.status = ClazzNode.STATUS_KNOWN;
2461+
ClazzLoader.loadedScripts[n.path] = false;
2462+
}
2463+
var path = ClazzLoader.getClasspathFor (qClazzName);
2464+
ClazzLoader.loadedScripts[path] = false;
2465+
if (ClazzLoader.innerLoadedScripts[path]) {
2466+
ClazzLoader.innerLoadedScripts[path] = false;
2467+
}
2468+
2469+
if (window["ClassLoaderProgressMonitor"] != null) {
2470+
ClassLoaderProgressMonitor.showStatus ("Class " + qClazzName + " is unloaded.", true);
2471+
}
2472+
};
2473+
2474+
ClazzLoader.lastHotspotUpdated = new Date ().getTime ();
2475+
ClazzLoader.lastHotspotSessionID = 0;
2476+
2477+
/*
2478+
* This method will be called in server-return-script:
2479+
*
2480+
* ClazzLoader.updateHotspot (
2481+
* 134324344, 1, "org.eclipse.swt.widgets.Menu",
2482+
* 134324345, 2, "org.eclipse.swt.widgets.MenuItem",
2483+
* null);
2484+
*
2485+
*/
2486+
/* public */
2487+
ClazzLoader.updateHotspot = function () {
2488+
var length = (arguments.length - 1) / 3;
2489+
var lastID = 0;
2490+
var lastUpdated = 0;
2491+
var toUpdateClasses = new Array ();
2492+
for (var i = 0; i < length; i++) {
2493+
var time = arguments[i * 3];
2494+
var id = arguments[i * 3 + 1];
2495+
var clazz = arguments[i * 3 + 2];
2496+
if ((time > ClazzLoader.lastHotspotUpdated)
2497+
|| (time == ClazzLoader.lastHotspotUpdated
2498+
&& id > ClazzLoader.lastHotspotSessionID)) {
2499+
toUpdateClasses[toUpdateClasses.length] = clazz;
2500+
lastID = id;
2501+
lastUpdated = time;
2502+
}
2503+
}
2504+
if (toUpdateClasses.length > 0) {
2505+
ClazzLoader.lastHotspotUpdated = lastUpdated;
2506+
ClazzLoader.lastHotspotSessionID = lastID;
2507+
var needUpdateClasses = new Array ();
2508+
for (var i = 0; i < toUpdateClasses.length; i++) {
2509+
needUpdateClasses[i] = Clazz.unloadClass (toUpdateClasses[i]);
2510+
}
2511+
for (var i = 0; i < toUpdateClasses.length; i++) {
2512+
if (needUpdateClasses[i]) {
2513+
var clzz = toUpdateClasses[i];
2514+
ClazzLoader.loadClass (clzz, (function (clazz) {
2515+
return function () {
2516+
// succeeded!
2517+
if (window["ClassLoaderProgressMonitor"] != null) {
2518+
ClassLoaderProgressMonitor.showStatus ("Class " + qClazzName + " is reloaded.", true);
2519+
}
2520+
Clazz.unloadedClasses[clazz] = null;
2521+
};
2522+
}) (clzz));
2523+
}
2524+
}
2525+
}
2526+
ClazzLoader.lastHotspotJSFailed = false;
2527+
};
2528+
2529+
/* private */
2530+
ClazzLoader.removeHotspotScriptNode = function (n) {
2531+
// lazily remove script nodes.
2532+
window.setTimeout ((function (node) {
2533+
return function () {
2534+
if (node.readyState != "interactive") {
2535+
try {
2536+
if (node.parentNode != null) {
2537+
node.parentNode.removeChild (node);
2538+
}
2539+
} catch (e) { }
2540+
}
2541+
};
2542+
}) (n), 1);
2543+
2544+
if (ClazzLoader.hotspotMonitoringTimeout != null) {
2545+
window.clearTimeout (ClazzLoader.hotspotMonitoringTimeout);
2546+
ClazzLoader.hotspotMonitoringTimeout = null;
2547+
}
2548+
};
2549+
2550+
ClazzLoader.lastHotspotScriptLoaded = true;
2551+
ClazzLoader.hotspotMonitoringTimeout = null;
2552+
ClazzLoader.lastHotspotJSFailed = false;
2553+
2554+
/* protected */
2555+
ClazzLoader.hotspotMonitoring = function () {
2556+
if (ClazzLoader.lastHotspotScriptLoaded) {
2557+
var port = window["j2s.hotspot.port"];
2558+
if (port == null) {
2559+
port = 1725;
2560+
}
2561+
var hotspotURL = "http://127.0.0.1:" + port;
2562+
if (ClazzLoader.lastHotspotSessionID == 0) {
2563+
hotspotURL += "/hotspot.js";
2564+
} else {
2565+
hotspotURL += "/" + ClazzLoader.lastHotspotSessionID + ".js";
2566+
}
2567+
var script = document.createElement ("SCRIPT");
2568+
script.type = "text/javascript";
2569+
script.src = hotspotURL;
2570+
if (typeof (script.onreadystatechange) == "undefined") { // W3C
2571+
script.onload = script.onerror = function () {
2572+
ClazzLoader.lastHotspotScriptLoaded = true;
2573+
ClazzLoader.removeHotspotScriptNode (this);
2574+
};
2575+
} else {
2576+
script.onreadystatechange = function () {
2577+
var state = "" + this.readyState;
2578+
if (state == "loaded" || state == "complete") {
2579+
ClazzLoader.lastHotspotScriptLoaded = true;
2580+
ClazzLoader.removeHotspotScriptNode (this);
2581+
}
2582+
};
2583+
}
2584+
2585+
ClazzLoader.lastHotspotJSFailed = true;
2586+
ClazzLoader.lastHotspotScriptLoaded = false;
2587+
var head = document.getElementsByTagName ("HEAD")[0];
2588+
head.appendChild (script);
2589+
}
2590+
2591+
window.setTimeout (ClazzLoader.hotspotMonitoring, 250);
2592+
if (ClazzLoader.hotspotMonitoringTimeout == null) {
2593+
ClazzLoader.hotspotMonitoringTimeout = window.setTimeout (function () {
2594+
ClazzLoader.lastHotspotScriptLoaded = true; // timeout
2595+
window.setTimeout (ClazzLoader.hotspotMonitoring, 50);
2596+
}, 7500); // 7.5 seconds to time out
2597+
}
2598+
};
2599+
24262600
/*
24272601
* Remove j2slib.z.js, j2slibcore.z.js or Class/Ext/Loader/.js.
24282602
*/
@@ -2437,6 +2611,10 @@ window.setTimeout (function () {
24372611
break;
24382612
}
24392613
}
2614+
/* start ClazzLoader hotspot monitoring after 1 second */
2615+
if (window["j2s.script.debugging"] == true) {
2616+
window.setTimeout (ClazzLoader.hotspotMonitoring, 1000);
2617+
}
24402618
}, 324); // 0.324 seconds is considered as enough before refresh action
24412619

24422620
ClassLoader = ClazzLoader;

0 commit comments

Comments
 (0)