欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    鑒于 Oracle 最近對 Java 許可模式的變更,了解在您的環境中運行 Oracle Java 的風險和暴露至關重要。

    譯自 How To Protect Your Java Against Licensing Liability Risks,作者 Jay Patel。

    因此,您已從您的環境中刪除了所有需要昂貴的 Oracle Java SE 通用許可證的 Oracle JDK,該許可證與 Oracle 主協議 (OMA) 相關。但是,現在您需要阻止 Oracle Java 偷偷潛入并觸發對 Oracle 的新許可義務。以下介紹了禁用 JavaUpdater 和其他當前和常見方法、它們的有效性和缺點,以及提供了一些供您考慮的其他機制。

    背景

    2023 年 1 月,Oracle 將 Java 的許可要求更改為“所有員工指標”。具體內容應在他們的實際協議中進行審查,但為了討論的目的,讓我們將該協議改寫為:如果您安裝了一個或多個 Oracle Java SE 實例,無論安裝位置如何,都屬于 Oracle 技術網絡 (OTN) 許可證,您的組織可能需要遵守“所有員工”許可要求,無論有多少員工使用 Java 甚至擁有或使用計算機。您組織可能面臨的重大財務風險需要持續警惕。

    Oracle Java 如何重新進入?

    Oracle Java 可以通過多種方式安裝或更新。其中一些方法僅適用于桌面;一些適用于服務器。應考慮這兩種環境,因為它們都受相同的 Oracle 許可要求約束。Oracle Java 可以通過多種方式安裝或更新。

    • 用戶直接從 download.java.com 或 oracle.com/downloads 下載。
    • 用戶從外部維護的鏡像站點下載。
    • JavaUpdater 后臺進程 - (在 Windows 桌面)與 Oracle Java 開發工具包(JDK) 或 Java 運行時環境 (JRE) 一起安裝。- Java 控制面板小程序 - 允許一鍵更新現有 JVM(Java 虛擬機)/JDK。
    • 遷移前創建的黃金或其他基本虛擬桌面基礎設施 (VDI)/映像。
    • 您遷移 Java 之前進行的備份/恢復映像。
    • 操作系統便利通知 - 如果系統上未安裝 Java,并且用戶在命令提示符下鍵入“Java”,他們將收到一條消息,將他們指向 java.com。
    • 許多需要 Java 的傳統應用程序可能會提示用戶下載 Oracle Java;較新的應用程序通常會請求 OpenJDK,但并非所有應用程序都如此。
    • JavaScript - 有幾個函數使開發人員可以方便地呈現直接下載或可點擊按鈕,這些按鈕會重定向到 Oracle Java 網站。

    以下是針對上述重點內容的一些注意事項:

    阻止 java.com 和oracle.com/java/download還不夠

    Java 已經存在了近 30 年。在此期間,它經歷了許多迭代,包括從免費到付費,具體取決于提供商。由于 Java 的普及以及 Oracle Java 在許多用例中免費提供的事實,Oracle Java 通過許多網絡渠道、分銷合作伙伴和學術機構提供,其中許多機構沒有費心維護或刪除公開可用的 JDK 和 JRE 的完整功能副本。這些較舊的二進制文件從許可的角度來看通常不會造成麻煩(安全性是另一回事),但附帶的 Java 更新程序和 Java 控制面板小程序使用戶很容易無意中將其安裝更新到需要 Oracle 許可證的版本。

    我們將討論適用于最常見版本(Java 6-21)的策略,但您應該知道,Oracle Java 的某些特定版本需要許可證。這些版本是 8u211+、11、12、13、14、15、16。此外,Oracle 將“商業功能”的使用視為其許可要求的另一個觸發因素,例如使用其 MSI (Microsoft Windows 安裝程序) 或使用 JFR(Java Flight Recorder)。

    注意:2024 年 9 月,Oracle Java 17 也將需要付費的 OTN 許可證才能用于商業用途。

    做:

    • 阻止下載部分(如果可以,請阻止特定版本)。

    不要做:

    • 阻止整個域。Java.com 包含大量信息、文檔和討論,對參與 Java 社區的任何人都有幫助。

    禁用 Java 更新

    Oracle Java 包含一個默認情況下啟用的后臺(TSR 或終止并駐留)進程,用于檢查 Java 的新版本。

    如果不影響已安裝 Java 的當前工作狀態,這些項是可以禁用的。Azul 建議在注冊表級別將其移除或至少禁用這些項,并禁止用戶使用或重新啟用這些項。某些早期的 Oracle JVM/JRE/JDK 版本允許卸載更新器;較新的內部版本和版本不分離該組件。請注意,修改或移除 JDK 的任何部分都是 Oracle 條款的違規行為,然而,限制訪問任何文件并不違規。

    禁用 Java 控制面板 Applet

    Oracle Java JRE 中包含的控制面板小程序(Windows 上的 javacpl.exe)提供了一個圖形界面來控制 Oracle JVM 的許多方面。我將在這里提到 WebStart,即使它沒有與 Oracle JVM 分開,因為控制面板小程序與 WebStart 關系密切,并且等效功能由開源社區(在 IcedTea-Web 開源項目中)單獨實現。控制面板小程序包含一個選項卡,允許用戶通過以下幾種方式更新他們的 Java:

    通過設置自動化或單擊“立即更新”按鈕,用戶可以啟動下載其 JRE/JDK 的最新版本。

    做:

    • 完全禁用此功能,此界面中不再存在任何自助用戶級功能(刪除對 javacpl.exe 的訪問權限)。
    • 了解此界面操作的底層屬性文件,并在管理員級別修改/更新它們。
    • 在 Windows 上,您可以禁用 HLM:\SOFTWARE\JavaSoft\Java Update\Policy 下的兩個注冊表項“EnableJavaUpdate”和“EnableJavaUpdateCheck”(DWORD)。
    • 應該讓高級用戶了解 IcedTeaWeb-settings 界面,它取代了此功能的大部分內容。

    不要做:

    • 刪除 javacpl.exe - 這將違反 Oracle 的條款。

    更新 Golden 或其他基本 VDI/映像

    許多企業使用黃金映像來實例化虛擬機,用于各種用例,從快速現場測試和敏捷開發到生產級機器的標準化。這些映像通常包含通用或企業強制執行的軟件,并且可能包含用于服務器的 JRE 或用于開發映像的 JDK。由于這些映像在實例化之前一直處于脫機狀態,磁盤處于存檔狀態,因此它們可能處于休眠狀態,不會被正常的掃描/觀察機制捕獲。如果它們仍然存在于您的環境中,如果它們在生產場景中被實例化和使用,它們確實會構成風險。

    做:

    • 訪問您的 VDI/映像存儲庫以確定 Java 是否包含在標準構建或映像中。如果找到,請使用適當的二進制文件重新構建您的映像。
    • 如果您具有映像啟動前分類功能,請確保使用更新的 JVM。

    不要做:

    • 將替換的負擔放在映像用戶身上。
    • 允許臨時使用 Oracle JVM。
    • 假設短暫的映像是短暫的。

    刷新備份、恢復映像和快照

    隨著時間的推移,備份等將不再是一個問題;它們會自然地老化。但在遷移后的這段時間內,應特別注意跟蹤調用任何這些恢復機制的系統。應注意備份本身;據觀察,Oracle 在某些情況下已表明備份文件仍然可以輕松獲得并輕松啟用,因此構成許可證風險違規。從備份恢復的系統將受您現有的軟件執行策略的約束,因此請確保盡快捕獲并修復它們。修復后,應進行新的備份/快照,如果可能,應將以前的備份移至脫機狀態并使其“不可輕松獲得”。

    做:

    • 創建/更新不包含 Oracle Java 的快照。
    • 確保執行策略解決不必要的 Oracle Java 二進制文件的執行問題。

    不要做:

    • 忽略備份存檔,如果它可以使用,它將被使用。
    • 假設最終用戶會發現這種情況并進行修復。
    • 允許即使是更舊的(非 OTN)Java 也在未經檢查的情況下運行,至少檢查 Java 更新程序和 Java 控制面板設置。

    禁用操作系統和便捷更新

    如果用戶在命令提示符下鍵入“java”或應用程序在未初始化(沒有 Java)的 MacOS 系統上請求 Java,您將從操作系統收到一個響應,告訴您訪問 java.com:

    做:

    • 教育您的用戶群關于他們應該使用的 Java(基于企業標準或指南)。
    • 通過自助服務選項使 Java 易于獲得。由于存在許多選項和特定于應用程序的要求,因此期望應用程序和用戶遵守特定版本是不合理的。雖然允許 Java 主要版本靈活是安全的,但建議用戶盡可能選擇最新修補程序版本(主要版本)。
    • 考慮一個支持的 OpenJDK,其中包含及時的安全和修補程序更新。
    • 通過 dmg/rpm/msi 從 https://www.azul.com/downloads 安裝 Java 運行時。
    • 通過 homebrew 安裝/構建 JavaBrew install OpenJDK@<java version number>

    不要做: - 訪問 java.com 并安裝其中提到的任何版本。

    處理與應用程序打包在一起的 Java

    這種情況需要謹慎處理,并可能需要與軟件供應商進行溝通。有些應用程序在安裝過程中會合法地包含 Java JRE 或 JDK,例如使用 Java Compact Profile 的低功耗/物聯網設備、在網絡受限環境中使用的虛擬機映像等。在這些情況下,務必正確理解應用程序的支持要求和許可責任。

    在大多數情況下,供應商現在會支持其應用程序在 TCK(技術兼容性工具包)認證的 OpenJDK 構建 上運行。如果供應商確實將他們的軟件認證為 OpenJDK 兼容,那么選擇任何你想要的 OpenJDK 發行版就足夠了。供應商可能會認證特定發行版,但這可能是由于方便或他們缺乏了解。供應商應該將他們的測試視為針對 OpenJDK 規范,這意味著任何經過認證的 OpenJDK 都足夠。如果供應商使用特定于發行版的類,他們應該專門記錄該要求。

    在一些罕見的情況下,供應商會認為使用任何 JRE 而不是規定的 Oracle JRE 將使他們的支持合同失效。在這種情況下,你應該要求提供上述要求的書面文件,以及一份聲明,說明在你的環境中出于此目的使用 Oracle Java 不會使你的組織受到 Oracle 全員許可模式的約束。

    做:

    • 調查每個符合這種情況的應用程序。訪問供應商的網站或聯系他們的支持部門是一個好的開始。
    • 要求有關將應用程序遷移到 OpenJDK 的說明。不要期望遷移過程會遇到太多麻煩,特別是對于較新的 Java 版本。

    不要做:

    • 忽視這種情況。如果沒有明確的聲明免除你對 Oracle 的任何許可責任,在第三方應用程序中使用 Oracle JDK 會使你面臨許可風險。

    緩解來自外部網站的 JavaScript 或啟用

    只需一行簡單的腳本就可以創建一個 HTML 按鈕,讓用戶只需單擊一下即可下載 Oracle JDK,并創建一個新的許可責任。雖然這些情況通常超出了你的控制范圍,但你可以采取一些主動措施。

    做:

    • 教育你的用戶了解他們可用的已批準的 Java 選項。
    • 使相應的下載易于獲取。

    不要做:

    • 允許用戶繼續使用從 java.com 或 oracle.com 下載的 Java。

    一般建議

    防止持續的 Oracle Java 許可風險是可行的,但現在應該清楚的是,僅靠邊界策略不是最佳方法。它需要與緩解策略和合理的警惕性相結合。

    • 監控 Oracle Java 并盡快修復任何新的 Oracle Java 實例。用 OpenJDK 發行版替換 Oracle JDK 并不困難,并且幾乎不會帶來兼容性、穩定性或安全風險。你的新 Java(不是應用程序)供應商也應該能夠為此類工作提供指導。
    • 如果你有實時桌面管理解決方案可用(如 BeyondTrust、CyberArc 等),請使用它來禁用關鍵的 Java 安裝程序、可執行文件和啟動器(java.exe、javaw.exe、javaws.exe、jp2launcher.exe等)。
    • 在 Windows 上盡可能使用組策略。這是控制 Java 是否可以運行或安裝的更可靠方法,并且可以通過公司范圍的策略集中執行。
    • 使用文件系統掃描程序或清單工具來查看安裝注冊表之外的內容。像 Flexera 或 Microsoft Endpoint Configuration Manager(以前稱為 System Center Configuration Manager (SCCM))這樣的工具可以配置為定期運行完整的文件系統掃描。
    • Azul 為客戶提供訪問我們的 Azul 遷移咨詢工具,這是一組發現和遷移(shell)腳本示例,我們的團隊在協助遷移工作時使用這些腳本。

    結論

    由于 Java 的普遍性和 Oracle Java 許可模式的最新變化,如果你繼續允許 Oracle Java 在你的環境中運行,了解你的風險和暴露非常重要。

    避免代價高昂的許可責任需要持續的警惕和分類。以上指南作為“盡力而為”的方法提供,我相信還有其他機制可以將 Oracle Java 重新引入你的環境。

    請隨時發表評論并添加您認為可能影響他人的任何發現,我們將盡力提供有關如何進行分類的建議。如果您需要更多詳細信息或有任何不適合在公開論壇上分享的疑慮,請聯系 migration@azul.com,我們將直接回復您。

    前兩篇文章我介紹了AtomicInteger和AtomicIntegerArray,現在總結一下兩個類的特點。

    1:AtomicInteger是對單個變量進行原子操作的。
    2:AtomicIntegerArray是對數組中的元素進行原子操作的,而不是數組本身。
    

    本篇文章介紹第三類原子操作:AtomicIntegerFieldUpdater.

    1:關于private/protected/public訪問控制符
    2:AtomicIntegerFieldUpdater的一些限制
    3:AtomicIntegerFieldUpdater實例
    4:AtomicIntegerFieldUpdater源碼解析
    

    一、關于private/protected/public訪問控制符

    由于下面要用到Java這個知識點,所以我們在復習一下關于Java的訪問控制符,在Java中主要定義三個訪問控制符,還有一個默認的(沒有被任何訪問控制符修飾default),一共四個訪問控制符

    1:private:私有的,只能自己能訪問,其他都訪問不到
    2:默認的(default,如果沒有被任何訪問控制符修飾):同一類或者同一個包中能夠訪問到,其他訪問不到。
    3:protected:同一個類、子類、同一個包能放到,其他訪問不到。
    4:public:所有類都能訪問到。
    

    他們的訪問范圍如圖:

    通過一個表格更加清晰的看一下:

    這個知識點大家都非常熟悉了,理解了訪問控制符,AtomicIntegerFieldUpdater的一些知識點就好理解了。

    二、AtomicIntegerFieldUpdater的一些限制

    接下來的文章內容如果沒有特殊說明,AtomicIntegerFieldUpdater更新的字段簡稱為被操作的字段。

    1:被操作的字段必須被volatile修飾
    2:被操作的字段必須是int類型,不能是包裝類型,如Integer
    3:被操作的字段只能是實例變量,不能是類變量,就是不能被static修飾
    4:被操作的字段只能是可變變量,不能被final修飾,其實final和volatile不能同時存在,否則編譯不通過。
    5:如果調用方無法直接訪問到被操作字段,則會拋出異常
    

    關于第5點就是用到了上面所說的訪問控制權限:

    1:如果調用方和被操作字段所在的類是同一類,那么被操作字段可以被private/defalut/protected/public修飾。
    2:如果調用方和被操作字段所在的類是同一個包,那么被操作字段可以被defalut/protected/public修飾
    3:如果調用方和被操作字段所在的類屬于子類,那么被操作字段可以被protected/public修飾
    4:如果調用方和被操作字段所在的類不在同一個包,也不屬于子類關系,那么只能被public修飾。
    

    三、AtomicIntegerFieldUpdater實例

    上面提出了它的限制后,下面我們通過實例去一個一個的證明:

    1:首先證明AtomicIntegerFieldUpdater可以原子更新一個對象中被volatile修飾的int類型的字段

    下面的實例調用對象AtomicIntegerFieldUpdater和被操作字段所在的類在同一個包中

    調用對象:AtomicIntegerFieldUpdater

    package com.stqsht.juc.atomic;
    public class AtomicIntegerFieldUpdaterTest {
    //定義一個線程池
     private static ThreadPoolExecutor pool;
     static {
     pool=new ThreadPoolExecutor(5, 10, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1000));
     }
     public static void main(String[] args) throws InterruptedException {
     Obj obj=new Obj(0, 0);
     AtomicIntegerFieldUpdater<Obj> afu=AtomicIntegerFieldUpdater.newUpdater(Obj.class, "age");
     for (int i=0; i < 5; i++) {
     pool.execute(() -> {
     for (int j=0; j < 10000; j++) {
     obj.setId(obj.getId() + 1);
     afu.incrementAndGet(obj);
     }
     });
     }
     pool.awaitTermination(5, TimeUnit.SECONDS);
     System.out.println("id=" + obj.getId());
     System.out.println("age=" + obj.getAge());
     pool.shutdown();
     }
    }
    

    被操作字段所在的類Obj中有兩個字段,一個字段沒有被volatile修飾,一個字段被volatile修飾

    package com.stqsht.juc.atomic;
    class Obj {
     private int id;
     volatile int age;
     public Obj(int id, int age) {
     this.id=id;
     this.age=age;
     }
    //省略getter和setter方法
    }
    

    通過運行多次后,得出一個結論,每一次id的結果都不相同,而age得到的結果相同且是正確的,運行結果如下:

    從上述案例可以證明,AtomicIntegerFieldUpdater可以原子的更新一個對象中的字段。

    2:如果被操作的字段沒有關鍵字volatile,則會拋出異常:Must be volatile type

    class Obj {
     private int id;
     int age;
     public Obj(int id, int age) {
     this.id=id;
     this.age=age;
     }
    //setter和getter省略
    }
    

    上面的被修飾的字段age并沒有關鍵字volatile,運行代碼結果如下:

    從運行結果可以看出,如果被操作的字段沒有被volatile修飾,那么它直接拋出異常,因為多線程下volatile具有可見性和有序性。

    3:被操作的字段只能是int類型,不能是包裝類型Integer

    class Obj {
     private int id;
     volatile Integer age;
     public Obj(int id, int age) {
     this.id=id;
     this.age=age;
     }
    //setter和getter省略
    }
    

    上面的被操作字段是一個包裝類Integer,運行結果如下圖:

    4:被操作的字段只能是實例變量,不能是類變量,也就是被操作字段不能被static修飾

    class Obj {
     private int id;
     static volatile int age;
     public Obj(int id, int age) {
     this.id=id;
     this.age=age;
     }
    //setter和getter省略
    }
    

    運行結果如下圖:

    5:被操作的字段只能是可變變量,不能被final修飾,其實final和volatile不能同時存在,否則編譯不通過。

    6:如果調用方無法直接訪問到被操作字段,則會拋出異常

    6.1:如果調用方和被操作字段所在的類是同一個類,被操作字段可以被private/defalut/protected/public修飾

    public class User {
     public static void main(String[] args) {
     AtomicIntegerFieldUpdater<User>ai=AtomicIntegerFieldUpdater.newUpdater(User.class,"age");
     User user=new User(0);
     ai.incrementAndGet(user);
     System.out.println(user.getAge());
     }
    //可以被private/defalut/protected/public修飾
     private volatile int age;
     public User(int age) {
     this.age=age;
     }
    //省略setter和gettter方法
    }
    

    大家可以親自測試以下上面的demo,無論成員變量age被什么訪問控制符修飾,都是可以的。

    6.2:如果調用方和被操作字段所在的類在同一個包中,被操作字段可以被defalut/protected/public修飾,用private則會拋出異常

    調用方:Caller

    package com.stqsht.juc.other;
    import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
    //調用方
    public class Caller {
     public static void main(String[] args) {
     User user=new User(0);
     AtomicIntegerFieldUpdater<User> ai=AtomicIntegerFieldUpdater.newUpdater(User.class,"age");
     ai.incrementAndGet(user);
     System.out.println(user.getAge());
     }
    }
    

    被操作字段所在的類:User

    package com.stqsht.juc.other;
    //調用方
    public class User {
    //可以被default/protected/public修飾
     volatile int age;
     public User(int age) {
     this.age=age;
     }
     //省略setter和getter方法
    }
    

    如果上面的例子如果被private修飾,則會拋出如圖的異常:

    6.3:如果調用方和被操作字段所在的類屬于子類關系,被操作字段可以被protected/public修飾

    調用方:com.stqsht.juc.other.Caller

    package com.stqsht.juc.other;
    import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
    import com.stqsht.juc.common.User;
    //調用方
    public class Caller extends User {
     public static void main(String[] args) {
     Caller user=new Caller(0);
     AtomicIntegerFieldUpdater<User> ai=AtomicIntegerFieldUpdater.newUpdater(User.class,"age");
     ai.incrementAndGet(user);
     System.out.println(user.getAge());
     }
     public Caller(int age) {
     super(age);
     }
    }
    

    被操作字段所在的類:com.stqsht.juc.common.User

    package com.stqsht.juc.common;
    //被操作字段所在的類,可以被protect/public修飾
    public class User {
     volatile int age;
     public User(int age) {
     this.age=age;
     }
     public int getAge() {
     return age;
     }
     public void setAge(int age) {
     this.age=age;
     }
    }
    

    如果上面的例子被private/defalut修飾,則會拋出以下異常。

    6.4:如果調用方和被操作字段所在的類不在同一個包,也不屬于子類關系,那么只能被public修飾。

    調用方:com.stqsht.juc.other.Caller

    package com.stqsht.juc.other;
    import com.stqsht.juc.common.User;
    import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
    //調用方
    public class Caller {
     public static void main(String[] args) {
     User user=new User(0);
     AtomicIntegerFieldUpdater<User> ai=AtomicIntegerFieldUpdater.newUpdater(User.class, "age");
     ai.incrementAndGet(user);
     System.out.println(user.getAge());
     }
    }
    

    被操作字段所在的類:com.stqsht.juc.common.User

    package com.stqsht.juc.common;
    public class User {
     protected volatile int age;
     public User(int age) {
     this.age=age;
     }
     public int getAge() {
     return age;
     }
     public void setAge(int age) {
     this.age=age;
     }
    }
    

    如果上面的代碼被private/defalut/protected修飾,則會拋出如下異常

    上面列出了AtomicIntegerFieldUpdater的一些限制,我們知道了怎么使用AtomicIntegerFieldUpdaterle ,那從源碼角度,它是怎么有這些限制呢,我們進入它的源碼一探究竟。

    四、AtomicIntegerFieldUpdater源碼解析

    當我們跟進源碼中看到它是一個抽象類,它只有一個方法能夠獲取一個實例對象。

    public abstract class AtomicIntegerFieldUpdater<T> {
     
     @CallerSensitive
     public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass,
     String fieldName) {
     return new AtomicIntegerFieldUpdaterImpl<U>
     (tclass, fieldName, Reflection.getCallerClass());
     }
    //省略其他代碼
    }
    參數1:tclass:實例的Class對象,例如上面例子User.class
    參數2:fieldName:被操作的字段的名稱,例如上面例子成員變量age
    

    通過一個newUpdater()方法獲取一個實例對象,從這個方法中可以看出他的實現類是AtomicIntegerFieldUpdaterImpl,這個實現類在它的內部,我們一起跟進它的實現類。

    private static final class AtomicIntegerFieldUpdaterImpl<T>
    extends AtomicIntegerFieldUpdater<T> {
    //原子操作封裝對象
    private static final sun.misc.Unsafe U=sun.misc.Unsafe.getUnsafe();
    private final long offset;
    //調用方的Class對象,如上面例子Caller.class
    private final Class<?> cclass;
    //被操作字段所在的類的Class對象,如上面例子User.class
    private final Class<T> tclass;
    

    上面是子類的幾個重要的成員變量,下面我們看一下它的核心構造函數

    //參數一:tclass:被操作字段所在類的Class對象
    //參數二:被操作字段的名稱
    //參數三:調用方的Class對象
    AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
     final String fieldName,
     final Class<?> caller) {
     final Field field;
     final int modifiers;
     try {
    //通過反射獲取被操作字段
     field=AccessController.doPrivileged(
     new PrivilegedExceptionAction<Field>() {
     public Field run() throws NoSuchFieldException {
     return tclass.getDeclaredField(fieldName);
     }
     });
    //獲取被操作字段修飾符
     modifiers=field.getModifiers();
    //判斷訪問控制符的權限
     sun.reflect.misc.ReflectUtil.ensureMemberAccess(
     caller, tclass, null, modifiers);
     ClassLoader cl=tclass.getClassLoader();
     ClassLoader ccl=caller.getClassLoader();
     if ((ccl !=null) && (ccl !=cl) &&
     ((cl==null) || !isAncestor(cl, ccl))) {
     sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
     }
     } catch (PrivilegedActionException pae) {
     throw new RuntimeException(pae.getException());
     } catch (Exception ex) {
    //$5:如果調用方不能直接訪問被操作字段,則拋出異常
     throw new RuntimeException(ex);
     }
     if (field.getType() !=int.class)
    //$2:如果不是int類型,則會拋出異常
     throw new IllegalArgumentException("Must be integer type");
     if (!Modifier.isVolatile(modifiers))
    //$1:如果沒有被volatile修飾,則拋出異常
     throw new IllegalArgumentException("Must be volatile type");
     
     this.cclass=(Modifier.isProtected(modifiers) &&
     tclass.isAssignableFrom(caller) &&
     !isSamePackage(tclass, caller))
     ? caller : tclass;
     this.tclass=tclass;
    //$3:objectFieldOffset()方法的作用:獲取某個字段相對Java對象的起始地址的偏移地址
     this.offset=U.objectFieldOffset(field);
    }
    

    這個構造函數涵蓋了AtomicIntegerFieldUpdater的所有限制,所以從源碼角度也證明了上面總結的限制。這個構造函數的流程圖如下:

    AtomicIntegerFieldUpdater的核心方法和AtomicInteger類似,功能也是一樣的:原子更新一個被volatile修飾的變量,這里就不在介紹了,如果不太明白這些方法的用法,請進入我的主頁查看

    接下來介紹幾個特殊的方法:判斷調用方和被操作字段所在的類是否在同一個包,是否是子類關系。

    第一個方法:isAncestor:判斷是否屬于子類關系

    private static boolean isAncestor(ClassLoader first, ClassLoader second) {
     ClassLoader acl=first;
     do {
     acl=acl.getParent();
     if (second==acl) {
    //屬于子類,返回true
     return true;
     }
     } while (acl !=null);
     return false;
    }
    

    第二個方法:isSamePackage:判斷是否在同一個包

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有