public static void addJSCSRel(int jsObjID, object csObj, bool weakReference = false) { if (weakReference) { WeakReference wrObj = new WeakReference(csObj); var Rel = new JS_CS_Rel(jsObjID, wrObj); AddDictionary1(jsObjID, Rel); AddDictionary2(Rel); } else { JSCache.TypeInfo typeInfo = JSCache.GetTypeInfo(csObj.GetType()); if (mDictionary1.ContainsKey(jsObjID)) { if (typeInfo.IsValueType) { mDictionary1.Remove(jsObjID); } } var Rel = new JS_CS_Rel(jsObjID, csObj); AddDictionary1(jsObjID, Rel); if (typeInfo.IsClass) { AddDictionary2(Rel); } } }
private static void AddDictionary2(JS_CS_Rel Rel) { if (mDictionary2.ContainsKey(Rel.csObj)) { mDictionary2[Rel.csObj] = Rel; Debug.LogError("mDictionary2 has same key to add:" + Rel.csObj + " - " + Rel.jsObjID); } else { mDictionary2.Add(Rel.csObj, Rel); } }
private static void AddDictionary1(int jsObjID, JS_CS_Rel Rel) { if (mDictionary1.ContainsKey(jsObjID)) { mDictionary1[jsObjID] = Rel; Debug.LogError("mDictionary1 has same key to add:" + jsObjID + " - " + Rel.csObj); } else { mDictionary1.Add(jsObjID, Rel); } }
public static void addJSCSRel(int jsObjID, object csObj, bool weakReference = false) { //if (csObj == null || csObj.Equals(null)) // if (csObj != null && csObj is UnityEngine.Object) // { // if (csObj.Equals(null)) // { // Debug.LogError("JSMgr.addJSCSRel object == null, call stack:" + new System.Diagnostics.StackTrace().ToString()); // //throw new Exception(); // } // } if (weakReference) { int hash = csObj.GetHashCode(); WeakReference wrObj = new WeakReference(csObj); var Rel = new JS_CS_Rel(jsObjID, wrObj, hash); mDictionary1.Add(jsObjID, Rel); mDictionary2.Add(hash, Rel); } else { int hash = csObj.GetHashCode(); JSCache.TypeInfo typeInfo = JSCache.GetTypeInfo(csObj.GetType()); if (mDictionary1.ContainsKey(jsObjID)) { if (typeInfo.IsValueType) { mDictionary1.Remove(jsObjID); } } #if UNITY_EDITOR if (mDictionary1.ContainsKey(jsObjID)) { Debug.Log(">_<"); } #endif var Rel = new JS_CS_Rel(jsObjID, csObj, hash); mDictionary1.Add(jsObjID, Rel); if (typeInfo.IsClass) { mDictionary2.Add(hash, Rel); } } }
public static void changeJSObj(int jsObjID, object csObjNew) { if (!csObjNew.GetType().IsValueType) { Debug.LogError("class can not call changeJSObj2"); return; } JS_CS_Rel Rel; if (mDictionary1.TryGetValue(jsObjID, out Rel)) { mDictionary1[jsObjID] = new JS_CS_Rel(jsObjID, csObjNew); } }
public static void ShutdownJSEngine() { shutDown = true; /* * 在 Shutdown 时,先主动删除 CSRepresentedObject * 现在已经没有必要再维护 id -> CSR.. 的关系了 * 移除后,CSR.. 有可能还被其他地方引用,所以在这个函数中调用C# GC,也不一定会调用到 CSR.. 的析构 * 后来在某个时刻析构被调用,在析构函数里有 removeJSCSRel ,那里会判断 round 是上一轮的所以忽略 */ List <int> keysToRemove = new List <int>(); List <int> hashsToRemove = new List <int>(); foreach (var KV in mDictionary1) { JS_CS_Rel rel = KV.Value; if (rel.csObj is WeakReference) { if ((rel.csObj as WeakReference).Target is CSRepresentedObject) { keysToRemove.Add(KV.Key); hashsToRemove.Add(rel.hash); } } } foreach (var k in keysToRemove) { mDictionary1.Remove(k); } foreach (var h in hashsToRemove) { mDictionary2.Remove(h); } // // 并GC // System.GC.Collect(); int Count = mDictionary1.Count; // There is a JS_GC called inside JSApi.ShutdownJSEngine #if UNITY_EDITOR // DO NOT really cleanup everything, because we wanna start again JSApi.ShutdownJSEngine(0); #else JSApi.ShutdownJSEngine(1); #endif StringBuilder sb = new StringBuilder(); sb.AppendLine("After JSApi.ShutdownJSEngine: "); sb.Append("mDictionary1 count " + Count + " -> " + mDictionary1.Count + ", left elements(should only contain JSComponent):\n"); /* * 到这里 mDictionary1 和 mDictionary2 应该只剩余 JSComponent 及其子类,原因是: * 除了 JSComponent 外,其他东西都应该在 JSApi.ShutdownJSEngine(0) 后被移除(他里面调用了 JS_GC) * 而 JSComponent 是没有垃圾回收回调的,他是在 OnDestroy 时从这2个字典里移除的 * 这时候可能他的 OnDestroy 还没有执行,所以这2个字典里还会有他们 */ List <int> Keys = new List <int>(mDictionary1.Keys); foreach (var K in Keys) { if (!mDictionary1.ContainsKey(K)) { continue; } JS_CS_Rel Rel = mDictionary1[K]; sb.AppendLine(K.ToString() + " " + Rel.name); } Debug.Log(sb); allCallbackInfo.Clear(); JSMgr.MoveJSCSRel2Old(); mDictJSFun1.Clear(); mDictJSFun2.Clear(); evaluatedScript.Clear(); CSRepresentedObject.s_objCount = 0; CSRepresentedObject.s_funCount = 0; jsEngineRound++; }
public static void ShutdownJSEngine() { shutDown = true; // // remove CSRepresentedObject first // no need to maintain id -> CSRepresentedObject now // // after remove, CSRepresentedObject may still be referenced, and ~CSRepresentedObject may not be called // some times later ~CSRepresentedObject is called -> removeJSCSRel -> round is ignored because it is last round // List <int> keysToRemove = new List <int>(); List <int> hashsToRemove = new List <int>(); foreach (var KV in mDictionary1) { JS_CS_Rel rel = KV.Value; if (rel.csObj is WeakReference) { if ((rel.csObj as WeakReference).Target is CSRepresentedObject) { keysToRemove.Add(KV.Key); hashsToRemove.Add(rel.hash); } } } foreach (var k in keysToRemove) { mDictionary1.Remove(k); } foreach (var h in hashsToRemove) { mDictionary2.Remove(h); } System.GC.Collect(); int Count = mDictionary1.Count; // There is a JS_GC called inside JSApi.ShutdownJSEngine #if UNITY_EDITOR // DO NOT really cleanup everything, because we wanna start again JSApi.ShutdownJSEngine(0); #else JSApi.ShutdownJSEngine(1); #endif StringBuilder sb = new StringBuilder(); sb.AppendLine("After JSApi.ShutdownJSEngine: "); sb.Append("mDictionary1 count " + Count + " -> " + mDictionary1.Count + ", left elements(should only contain JSComponent):\n"); // // here, mDictionary1 and mDictionary2 should only contain JSComponent and his subclasses, because: // everything should be removed after JSApi.ShutdownJSEngine(0) (it calls calls JS_GC) // JSComponent is nomally be removed during OnDestroy, but his OnDestroy may not be called yet here // List <int> Keys = new List <int>(mDictionary1.Keys); foreach (var K in Keys) { if (!mDictionary1.ContainsKey(K)) { continue; } JS_CS_Rel Rel = mDictionary1[K]; sb.AppendLine(K.ToString() + " " + Rel.name); } Debug.Log(sb); allCallbackInfo.Clear(); JSMgr.MoveJSCSRel2Old(); mDictJSFun1.Clear(); mDictJSFun2.Clear(); evaluatedScript.Clear(); CSRepresentedObject.s_objCount = 0; CSRepresentedObject.s_funCount = 0; jsEngineRound++; }