<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    ASE'21:Java語言中Lambda表達式的誤用分析

    一顆小胡椒2022-03-07 08:10:53

    JDK8被認為是近年來Java最重要的一次更新。其引入的一系列函數式的編程特性,特別是lambda表達式,使這一典型的面向對象編程的語言具有了函數式編程范式。Java lambda表達式由三部分構成:參數列表、箭頭字符和lambda body。參數列表類似常規方法中的形參列表,lambda body是一個表達式。在Java中,lambda表達式可以賦值給變量,也可以作為參數傳遞給方法(對應的類為函數接口)。圖1展示了lambda表達式的語法結構以及和其對應的函數接口。

    圖1 Lambda表達式的句法結構和對應的函數接口

    一些研究人員發現從2014年JDK8更新至今,Java開發人員開始越來越多的使用lambda表達式。其被使用的原因主要包括了以下幾個方面:(i) 使現有代碼更加簡潔和可讀; (ii) 避免代碼重復,以及 (iii) 模擬函數的延遲計算特性等。此外,研究人員也發現有開發人員常常會低效地使用 Java 的內置函數式接口,即他們更喜歡使用通用的函數式接口而不是專用的接口,卻忽略了其可能帶來的性能開銷。類似的,我們也在開源項目中發現了越來越多由于誤用lambda表達式而引發的漏洞,缺陷,以及兼容性等問題。針對這些問題,我們開展了大量的實證研究,并取得了重要發現。

    該成果“Why Do Developers Remove Lambda Expressions in Java?”已在國際頂級會議ASE'21發表。相關實驗分析數據和代碼已開源。

    • 論文鏈接:
    • https://ieeexplore.ieee.org/document/9678600
    • 開源鏈接:
    • https://github.com/CGCL-codes/LambdaMisuse

    背景與動機

    圖2展示了在大型開源項目Lucene中,由于lambda表達式誤用而引入的一個真實內存泄露問題。在該示例中,nextSeq是函數advanceQueue中的一個final變量,并且是此函數唯一引用的外部變量。由于此lambda表達式僅引用了一個final的外部變量,因此被稱為無狀態的lambda表達式。在運行時該lambda表達式和靜態內部類非常類似,即在JVM運行開始時加載到JVM,JVM運行結束之后該對象會被回收。因此,這個函數每次調用時都會引用該lambda表達式中的nextSeqNo變量,并且這個引用會一直維持到JVM運行結束,而不會被JVM的Garbage Collector回收,這樣就會導致內存泄漏和大量的內存開銷,甚至可能導致內存溢出異常。為了修復該問題,開發人員刪除了該lambda表達式,并將其替換成了普通的函數調用。

    圖2 由lambda表達式導致的內存泄露問題及其修復

    我們觀察到,在開源項目中引入 lambda 表達式后,由于其引入的各種問題,開發人員將 其修改回傳統的代碼實現是非常普遍的。然而,目前還沒有研究工作系統地研究過使用lambda表達式帶來的問題及其嚴重性,以及lambda表達式不適用的場景。為了填補這個空白,我們對大型Java開源項目中的海量被刪除的lambda表達式的進行定量分析、定性分析以及面向開發者的實證研究調查,最終發現了由于誤用lambda表達式而導致的九種常見嚴重負面影響以及一系列不適宜使用lambda表達式的復雜場景。我們的工作為未來這方面的研究指明了方向,并且能夠幫助Java開發人員更好的利用lambda表達式。

    定量研究

    圖3 Java開源項目中被刪除的lambda表達式數量統計

    我們觀察到在Java開源項目中,lambda表達式被刪除是非常常見的現象,并且呈不斷上升的趨勢,如圖3所示。更糟糕的是,我們觀察到 lambda 表達式經常被誤用,在這種情況下,lambda 會導致缺陷漏洞或副作用,例如效率問題或內存泄漏。因此,研究開發人員不當使用和刪除的 lambda 表達式的特征引起了我們的極大興趣。我們通過對比被刪除的lambda表達式和高質量的lambda表達式的句法特征和語義特征,嘗試發現哪些lambda更可能被誤用以及刪除。具體來說,我們選取了103個大型的Apache的Java開源項目(至少1000個commit,10個committer)進行定量分析,從中提取了3662個被刪除的lambda表達式和31,228個被保留的lambda表達式。定量分析結果如圖4所示。通過對比這兩類lambda表達式的特征,我們有以下幾個主要發現:1)實現自定義函數接口的lambda表達式更容易被刪除;2)表達式主體更復雜的lambda表達式更容易被刪除;3)被自定義的函數調用的lambda表達式更容易被刪除。

    圖4 被刪除lambda表達式與高質量lambda表達式的定量分析

    定性研究

    我們也對lambda表達式的誤用進行了定性分析。具體來說,我們從Apache JIRA,GitHub Commits和GitHub Issues等來源收集了錯誤使用lambda表達式的實例,以及其導致的缺陷或漏洞問題。通過仔細研究,我們將這些lambda表達式引入的問題總結成了以下主要幾類:

    1) 性能下降。誤用lambda表達式可能導致內存泄漏,如圖2所示,lambda表達式可能在短時間內造成較大的內存開銷,導致程序性能下降。或者在頻繁調用的代碼語句中使用有狀態的lambda表達式,造成過量的對象內存分配,給Garbage Collector帶來巨大壓力,也會導致程序性能下降。

    2) 較差的可讀性。Lambda表達式的引入的動機之一是解決匿名內部類的“高度問題”。比如圖5左邊所示的匿名內部類5行代碼其實只有1行發揮了作用。轉化為lambda表達式之后能用1行代碼實現相同功能。但是,我們發現一些lambda表達式可能會引入“寬度問題”,即lambda表達式過于冗長從而影響了代碼的可讀性,如圖5所示。

    圖5 可轉換為lambda表達式的匿名內部類以及lambda引入的“寬度問題”

    3) 序列化問題。序列化是Java語言非常重要的功能,然而序列化lambda表達式是不被推薦的。因為序列化一個合成類(編譯lambda表達式時會產生lambda表達式對應的合成類)的方式在不同的JVM可能不同,因此可能存在兼容性問題。因此,在一個JVM上序列化一個lambda表達式然后在另一個JVM上反序列化這個lambda表達式可能會帶來兼容性問題。

    4) 較差的可擴展性。Java lambda表達式本質上對應一個函數接口(只含有一個抽象方法的接口)。但是在開發過程中,可能需要增加一些方法,而增加方法之后接口就不再是函數接口了,不能被lambda表達式實現,因此必須改成匿名內部類等。

    5) 類型推斷失敗。Lambda表達式的類型信息有時可以省略,而由編譯器來負責推斷。但是如果下上下文信息不足,會讓編譯器推斷類型失敗,從而引發錯誤。

    6) 較差的可維護性。由于lambda表達式編譯后產生一個合成類,并且合成類是沒有明確命名的(lambda表達式本身就相當于匿名類)。如果這個合成類運行時拋出異常,那么其所對應的Stack Trace可讀性就很差,如圖6所示,非常不利于程序的開發與維護。 

    圖6 Lambda表達式拋出異常之后的Stack Trace

    7)延遲計算。Lambda表達式的一個關鍵特性就是延遲計算。延遲計算就是指在需要的時候再對表達式進行求值。然而,開發人員往往在使用時忽略了這一特性,導致實現的功能出錯或引入其他問題。

    通過進一步對搜集數據的定性分析,我們總結了7種關于lambda表達式誤用的遷移模式,即開發人員是如何修復使用錯誤的lambda表達式的(具體請參見原文)。同時,我們也分析了在Java語言中lambda表達式的誤用情況(如上文總結所示)與遷移模式之間的關系,如圖7所示。最終,我們結合對lambda表達式誤用實例的理解、代碼遷移模式和開源項目中開發者的反饋,總結了一些使用lambda表達式的建議。例如不要在影響性能關鍵的代碼片段中使用lambda表達式;不要在條件分支處理的時候使用Java 8引入的API和lambda表達式;盡量在使用lambda表達式時指明變量與表達式類型;如果需要拋出檢查型異常,則不要使用lambda表達式;盡量避免使用太復雜的lambda表達式等。我們的工作不僅為未來的相關研究指明了方向,同時也能夠幫助Java開發人員更好的利用lambda表達式這一函數式特性。

    圖7 Lambda表達式的誤用情況與遷移模式之間的關系

    詳細內容參見: 

    Zheng, Mingwei, Jun Yang, Ming Wen, Hengcheng Zhu, Yepang Liu, and Hai Jin. "Why Do Developers Remove Lambda Expressions in Java?" In 2021 36th IEEE/ACM International Conference on Automated Software Engineering (ASE), pp. 67-78. IEEE, 2021.

    lambda
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    情景展示 原因分析 解決方案 情景展示如上圖所示,我們想要終止 for 循環,使用 return。 執行結果如下:
    前言 1、這篇文章講了什么? 文本圍繞三個問題 lambda會遇到什么攻擊場景 什么情況下,在lambda中讀取到的env環境變量密鑰可以讓我們接管服務器甚至整個賬號 什么情況下,可以通過lambda權限去橫向到其他的EC2服務器 本文會對這三個問題進行解答,并且進行演示
    盡管發現的首個樣本危害不大,但已經能夠看到攻擊者是如何利用云專業知識入侵復雜的云基礎設施。
    JDK8是近年來Java最重要的一次更新。其引入的一系列函數式編程特性,例如lambda表達式,已經被Java開發者廣泛使用。然而,lambda的使用也存在缺陷漏洞以及兼容性等問題。我們針對這些問題開展了實證研究并獲得了重要發現。
    這種新的惡意軟件被Cado安全研究人員稱為Dennia。
    他們直接聯系AWS API,進一步枚舉帳戶,進而收集信息和泄露數據。不幸的是,AWS集群角色錯誤配置,擁有過大的讀取權限。本意是允許讀取特定的S3存儲桶,但權限允許角色讀取帳戶中的一切,這使攻擊者得以進一步了解AWS帳戶,包括Lambda。受影響的AWS帳戶中有不同的Lambda函數,主要與帳戶自動化有關。還有證據表明攻擊者執行了盜取的軟件。
    日本國家級應急響應機構的職能由 NISC 與 JPCERT/CC 共同負責,JPCERT/CC 在惡意軟件分析領域中做了許多探索和實踐。
    根據代碼得出 sb的值為頁碼+時間戳 "page=21652931584"。再次hook Sign函數查看參數和返回值并與fiddler對比。此時已經可以斷定,這個Sign就是翻頁的加密函數 。我們用python實現一下。此時直接調用sign生成加密參數,抓取100頁的值相加得出flag:#!
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类