中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么分析JSBinding + SharpKit 內存管理與垃圾回收的原理

發布時間:2021-12-03 16:36:49 來源:億速云 閱讀:95 作者:柒染 欄目:大數據

本篇文章給大家分享的是有關怎么分析JSBinding + SharpKit 內存管理與垃圾回收的原理,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

C# 和 JS 都有垃圾回收機制,需要保證 2 者能夠分工協作。

類對象

類在C#中是引用類型。我們在 C# 中維護了2個map,保存 C# 對象和 JS 對象的一一對應關系。

舉一個例子,看以下代碼

1 // C#
2 List<int> lst = new List<int>();
3 
4 // JS
5 var lst = new System.Collections.Generic.List$1.ctor(System.Int32.ctor);

從C#返回一個對象到 JS 以及后續的過程是這樣的:

1) C# 獲得一個表示JS對象的ID。

1 // 文件:System_Collections_Generic_List77.javascript
2 _jstype.definition.ctor = function(t0) { CS.Call(5, 249, 0, true, this, t0.getNativeType()); } // 1) 這里的 this 傳到 C#后,C#得到一個對象ID

2) C# 創建一個 List csObj 對象。

3) 保存2種對象的一一對應關系。

1 // 存儲對應關系,偽代碼,具體可看 JSMgr.addJSCSRel 函數!
2 map1[jsObjID] = csObj;
3 map2[csObj.hashCode] = jsObjID;

注意,由于我們保存了 csObj 對象,那么我們必須在某個時刻就把他從map中移除,否則這個對象永遠不會被C# GC 給回收。

4) 給 JS 對象注冊 finalizer 回調函數,當他被 JS GC 回收時,會通知我們的回調。

在回調中做的事情就是從map中移除對 csObj 的引用,這樣我們就沒有主動握住  csObj 了,那他到某個時刻 自然就被回收了。

1 // 文件:System_Collections_Generic_List77Generated.cs
 2 
 3 static bool ListA1_ListA11(JSVCall vc, int argc)
 4 {
 5     int _this = JSApi.getObject((int)JSApi.GetType.Arg); // 1) 獲取JS對象ID
 6     JSApi.attachFinalizerObject(_this); // 4) 給 JS 對象注冊 finalizer 函數,當他被垃圾回收時,會通知我們的回調
 7     --argc;
 8 
 9     ConstructorInfo constructor = JSDataExchangeMgr.makeGenericConstructor(typeof(System.Collections.Generic.List<>), constructorID0); 
10     if (constructor == null) return true;
11 
12     int len = argc - 1;
13     if (len == 0)
14     {
15         JSMgr.addJSCSRel(_this, 
               constructor.Invoke(null, new object[]{}));// 2), 3) 創建 C# 對象,保存一一對應關系 16     } 17 18     return true; 19 }

5) 任何時刻,當要從C#返回一個對象到JS時,都會查找是否已經有對應的 JS 對象了。如果有,就返回已經保存的那個。如果沒有,才創建一個對應的 JS 對象返回給 JS。

小結:對于類對象,我們存儲了JS對象和CS對象的一一對應關系。JS對象仍然是完全受 JS GC 管理,什么該被回收就什么時候被回收。而對于CS對象,通過往JS對象注冊垃圾回收事件,當JS對象被回收時我們將得到通知,那時候我們就可以主動去除對CS對象的引用了。

結構體對象

結構體在C#中是值類型的。不可能存儲一一對應關系。從C#返回結構體對象到JS時,每次都重新創建一個對象出來,返回給JS。只能通過JS對象找到對應的C#對象,反過來是行不通的。

存儲關系變成:

1 // 存儲對應關系,偽代碼,具體可看 JSMgr.addJSCSRel 函數!
2 map1[jsObjID] = csObj; 3 // map2[csObj.hashCode] = jsObjID; // 沒有這個了!

垃圾回收控制跟類對象是一樣的。

注意:目前代碼里 Vector2,Vector3 是用JS寫了一遍(以后還會增加)。他們和上面說到的結構體對象的存儲方法沒有什么關系。

每當 從 JS->CS 時,根據JS對象的xyz值構造一個C#對象來使用。

每個從 CS->JS 時,根據CS對象的xyz值構造一個 JS 對象。

(不好理解?想象一下 int 如何 JS->CS,CS->JS? 目前V2, V3和 int 的傳遞是類似的,在 JS 和 CS 端都各有各自的數據結構)

(還是不好理解?群里問吧,或者問我)

純JS對象在C#中的存儲

上面所說的類對象和結構體對象的存儲有一個共同點:JS和CS兩端都知道要存儲的對象類型是什么。比如說 List,GameObject,2邊都很了解這2個類,都能對他們的對象進行處理。

純JS對象是指,只有JS有類定義,C#并不清楚這個類。

1 // JS 代碼
 2 
 3 JsTypes.push( {
 4     fullname: "DebugMessages.Message",
 5     Kind: "Class",
 6     definition: {
 7         ctor: function (txt){
 8             this.txt = txt;
 9         }
10     }
11 });
12 
13 var l = new System.Collections.Generic.List$1.ctor(DebugMessages.Message.ctor);
14 l.Add(new DebugMessages.Message("hello");
15 l.Add(new DebugMessages.Message("world");

Line13,創建一個 List,C#端構造 List 時會發現類型名是 "DebugMessage.Message",根據這個名字查找不到 System.Type(請看 JSDataExchange.GetTypeByName 函數)。

怎么辦呢?可不可以這樣,當C#找不到類型的時候,就直接用 List<int>,int表示JS對象ID。這樣不是挺好嗎?

是的,一開始就是這么做的。請看 Line14,new一個JS對象并傳遞給C#,C#存儲了他的ID,看起來很美好。

但!是!這個JS對象接下去就沒有人引用他了,如果發生GC,那個對象就要被回收。而C#那邊還存著一個int,等一下要用的時候就找不著JS對象了……

當你把一個JS函數設置給C# Delegate 時,也存在相同的問題。

所以,在C#中存儲這個JS對象時,要增加JS對象的引用!

我增加了一個 CSRepresentedObject 類,來完成這個功能。

(這里面還多了個小細節:使用了 WeakReference 類,具體可以看下代碼,缺他好像不行)

1 public class CSRepresentedObject
 2 {
 3     public static int s_objCount = 0;
 4     public static int s_funCount = 0;
 5 
 6     //不要直接創建這個對象,應該調用 JSDataExchangeMgr.getObject
 7     public CSRepresentedObject(int jsObjID, bool bFunction = false)
 8     {
 9         this.jsEngineRound = JSMgr.jsEngineRound;
10         this.jsObjID = jsObjID;
11         this.bFunction = bFunction;
12         JSMgr.addJSCSRel(jsObjID, this, true);
13 
14         if (bFunction) 
15             s_funCount++;
16         else 
17             s_objCount++;
18 
19         // 通常是1,不會加的
20         int refCount = JSApi.incRefCount(jsObjID);
21         //Debug.Log(new StringBuilder().AppendFormat("+ CSRepresentedObject {0} Ref[{1}] Fun[{1}]", jsObjID, refCount, bFunction ? 1 : 0));
22     }
23     ~CSRepresentedObject()
24     {
25         if (bFunction)
26             s_funCount--;
27         else 
28             s_objCount--;
29 
30         int refCount = JSApi.decRefCount(jsObjID);
31         if (refCount <= 0)
32         {
33             JSMgr.removeJSCSRel(jsObjID, this.jsEngineRound);
34             if (bFunction)
35             {
36                 JSMgr.removeJSFunCSDelegateRel(jsObjID);
37             }
38         }
39         else
40         {
41             Debug.LogError(";;;//IIL.x&");
42         }
43         //Debug.Log(new StringBuilder().AppendFormat("- CSRepresentedObject {0} Ref[{1}] Fun[{1}]", jsObjID, refCount, bFunction ? 1 : 0));
44     }
45     public int jsObjID;
46     public bool bFunction;
47     int jsEngineRound;
48 }

純C#對象在JS中的存儲

目前已知這種情況只發生在,當傳遞一個C#函數到JS時。(例子:TestEasingFunctions.cs)

在JS中也定義了一個叫做 JSRepresentedObject 的類來處理。(myclrhandler.javascript)

不過比上一種情況要簡單得多。這種情況處理后就變成和 “類對象” 一毛一樣了。

注意:C#對象存儲在JS中,JS根本無法使用拿到的C#對象,他只能起到一個過渡作用而已。

JS對象存儲在C#中也是一樣的。

以上就是怎么分析JSBinding + SharpKit 內存管理與垃圾回收的原理,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

读书| 安顺市| 韶关市| 禹州市| 磴口县| 白朗县| 宝丰县| 博客| 昭平县| 内丘县| 泗水县| 巴中市| 延庆县| 平潭县| 焦作市| 靖安县| 茂名市| 红安县| 内黄县| 宜宾县| 从江县| 宣汉县| 郸城县| 盱眙县| 乌兰察布市| 乌拉特前旗| 彰化县| 武隆县| 义马市| 沿河| 渭南市| 吉水县| 门头沟区| 南木林县| 政和县| 山阴县| 防城港市| 乌兰察布市| 榕江县| 密云县| 泰顺县|