KVM具有獨立於機器的、可移植的線程模型,可以獨立於Java語言運行.
其變化如下:
1.0之前
使用了一個簡單的循環調度模型,其中系統中的所有活動線程都存儲在循環列表中.
列表中的線程根據每個任務的Java級優先級,一個接一個地執行。在實現級別,線程優先級只是一個整數,它告訴解釋器在下一個線程切換髮生之前,線程可以執行多少原語。在每個字節碼執行之後,線程的“Timeslice”計數器將遞減。當時間片變爲零時,將強制執行線程切換。一些I/O原語也可以啓動線程切換。
1.0
加入了異步(非阻塞)I/O。
另一個目標是引入輕鬆實現替代調度機制的能力,但不太徹底地改變現有系統。
在最初的系統環境中,許多地方發生了切換。現在,它只在解釋器調度循環的頂部完成。在原始版本中,可運行的線程與當前正在執行的線程一起保存在循環列表中。現在,當線程開始執行時,每個線程都會從可運行線程的循環列表中刪除,當線程被阻塞時,會返回到循環列表中。
變量up已重命名爲當前線程,並指向當前正在執行的線程。一個新的變量runnable threads指向可運行線程的循環列表。
suspendThread() 方法有所改變.
它以前有一個要掛起哪個線程的參數,但在任何情況下都不能掛起,所以該參數已被刪除。這個例程用於執行上下文切換,但現在它只將currentThread置零,並調用一個名爲signalTimeToReschedule()的新函數,該函數向解釋器發出信號,表示在執行下一個字節碼之前應該重新調度VM。
爲解釋器提供了一個新的函數istimeToReschedule()來測試這種情況,並調用了一個新的函數reschedule()來測試這種情況。解釋器字節碼調度循環頂部的代碼現在是:
if (isTimeToReshedule()) {
reschedule();
}
isTimeToReshedule() 爲宏,宏展開後爲: Timeslice-- == 0.signalTimeToReschedule()也會宏,其只是將Timeslice 設置爲0.
並定義瞭如下方法:
-
startThread()
標記線程存活,但是是暫停狀態
-
resumeThread()
此函數將線程放回可運行線程列表(runnablethreads),如果激活的線程的優先級高於當前執行的線程的優先級,也將調用signalTimeToReschedule()。
-
BuildThread()
現在,這會將所有新線程添加到另一個名爲all threads的活動線程列表中。此列表由垃圾收集器使用。
-
DismantleThread()
從AllThreads 中移除
-
stopThread()
此函數與buildThread()的邏輯相反。它掛起線程並調用Dismantlethread()。
-
resumeThread()
這將替換使用ActivateThread()重新啓動掛起的線程。
-
isActivated()
在調用這個例程之前,必須測試currentThread是否爲非空
-
HandleEvent()
因爲原始handleEvent例程調用了ActivateThread,所以它不需要任何更改(isActivated()的調用約定除外)。 但是,返回參數的含義現在略有不同,這意味着向runnablethreads添加了一個新線程,而不是它只是切換了上下文。
-
SwitchThread()
switchthread現在只從reschedule()調用。當前線程可以指向線程,也可以不指向線程。如果這樣,我們會像以前一樣通過runnablethreads列表旋轉線程。如果它爲空並且runnablethreads列表爲空,則函數返回false,並且reschedule()必須決定要做什麼。
-
JLT_Yield()
只在signalTimeToReschedule()中調用
此外,還支持了異步i/0.
1.0.3
kvm 1.0.3有一個新的monitor/synchronization實現。
線程模型
在kvm中內部,爲每個線程實例化以下結構之一:
- THREAD : 是一種內部(VM級)結構,用於存儲獨立於Java級的東西來實現搶佔任務切換的必要信息。活動線程單獨鏈接到包含系統中所有活動線程的線性列表。
- JAVATHREAD: JAVATHREAD被映射到Java類“Thread.java”中定義的實例結構。它是從線程引用的。
爲什麼定義這兩個結構? 其原因是爲了便於移植,kvm希望保持線程系統實現與Java語言無關。
其中THREAD定義如下:
struct threadQueue {
THREAD nextAliveThread; /* alive線程隊列 */
THREAD nextThread; /* 運行或等待線程隊列 */
JAVATHREAD javaThread; /* 包含java 級別的線程信息 */
long timeslice; /* 從Java級線程優先級計算而來*/
STACK stack; /* 該線程的執行棧*/
/*
* 以下四個變量用於在線程可運行時存儲線程的虛擬機寄存器(=active,但不是當前給定的處理器時間)。
* 爲了方便垃圾收集,我們將指向執行堆棧的指針存儲爲偏移量,而不是實際指針。
* */
BYTE* ipStore; /* 程序計數器*/
FRAME fpStore; /* 幀*/
cell* spStore; /* sp*/
cell* nativeLp; /* 在KNI的調用中用來訪問本地變量*/
MONITOR monitor; /* 當前線程的monitor*/
short monitor_depth;
THREAD nextAlarmThread; /* 在當前隊列中的下一個線程 */
long wakeupTime[2]; /* 我們不能要求堆對象的8字節對齊 */
void (*wakeupCall)(THREAD); /* 線程喚醒時調用 */
struct {
int depth;
long hashCode;
} extendedLock; /* 在FASTLOCK時使用*/
char* pendingException; /* 線程將要拋出異常的類名 */
char* exceptionMessage; /* 要拋出異常的信息 */
enum {
THREAD_JUST_BORN = 1, /* 還沒有啓動 */
THREAD_ACTIVE = 2, /* 當前正在運行,或者在等待運行的隊列中 */
THREAD_SUSPENDED = 4, /* 等待monitor或者alarm */
THREAD_DEAD = 8, /* 線程退出 */
THREAD_MONITOR_WAIT = 16,
THREAD_CONVAR_WAIT = 32,
THREAD_DBG_SUSPENDED = 64
} state; // 線程狀態定義
bool_t isPendingInterrupt; /* Don't perform next sleep or wait */
#if ENABLE_JAVA_DEBUGGER
bool_t isStepping;
bool_t isAtBreakpoint;
bool_t needEvent;
CEModPtr debugEvent;
ByteCode nextOpcode;
struct singleStep_mod stepInfo;
int debugSuspendCount;
#endif /* ENABLE_JAVA_DEBUGGER */
};
JAVATHREAD定義如下:
struct javaThreadStruct { /* (A true Java object instance) */
COMMON_OBJECT_INFO(INSTANCE_CLASS)
long priority; /* 線程的優先級*/
THREAD VMthread; /* 執行vm thread */
INSTANCE target; /* 執行run的對象 */
SHORTARRAY name; /* 線程名稱*/
};