記一次調試

這是我最近幾個月來遇到的最棘手的一個問題:
* 昨天花了4個小時找出第一層次的原因
這個糾結啊,本來和老婆說好準時下班回家吃飯的,結果被這個問題拖了老久。

這是一個gradle的plugin,用來resolve公司內部的dependency的,弄完了跑測試項目的,拋一個NPE,而且NPE還不在自己的代碼里面。好吧,把gradle的源代碼翻出來看,如果是自己傳進去的一個值是null,解決起來也還ok了。結果到里面一看,那是一個loop里面,迭代map的時候出的錯 - 可以算是NPE中的最壞情況了把。仔細查看一下代碼,好吧,是迭代環境變量的。那行,在自己的代碼里把環境變量都打出來誰是null吧。結果全ok,看來是順序問題,在我打出來的時候,那個null的還是設上呢。既然是環境變量被設,那就在自己的代碼里搜搜看有沒有可疑點吧,還真找到個地方,一print還是真是在那個地方把PATH設成了null。

照理犯罪現場找到了,解決也就三下兩下的事了,于是我打算解決完,發完code review再走。結果發現那個null是被這么設上的:
env_path = plugin_ext.getCompileTimeJNI(jniPaths)

這是groovy語言,plugin_ext是一個gradle的plugin的extension,getCompileTimeJNI是定義在extension中的一個closure,我死活檢查getCompileTimeJNI,他也絕對不可能返回null,如果有exception的話,也應該拋出來,而不是返回null。

仔細檢查代碼,理清邏輯,打印結果,還是毫無頭緒,無奈已經7:30多了,還是先回去吧。

* 今天早上大概也兩個小時吧,找出的根本原因
周六早上起來, 多少還惦記著這件事,再看看吧。
終于,在觀察打印出來的結果時,我注意到一個細節:在打印plugin_ext.getCompileTimeJNI的時候:
第一次是closure的地址
然后調用closure:plugin_ext.getCompileTimeJNI(jniPaths)
第二次就是一個Set了

這說明這個closure的調用有點蹊蹺,我已經檢查過了closure的實現本身沒有問題,那么問題就在這簡簡單單的一句closure的調用上。 這花了我很長的時間去發現并相信著其實不是一個函數調用,而是一個賦值:
plugin_ext.getCompileTimeJNI(jniPaths)
就是
plugin_ext.getCompileTimeJNI = jniPaths
我不知道為什么gradle要發明這么坑爹的語法 - 這絕對是編碼質量與效率的殺手,但是不管怎樣,根源問題是找到了:
env_path = plugin_ext.getCompileTimeJNI(jniPaths)
這個賦值語句永遠返回null

* 暫時有了一個workaround,還沒有比較official的解決方案(if there is one)
你當然可以plugin_ext.getCompileTimeJNI,call,這是這改變了原有api的調用方式,是個breaking change,而且巨丑無比。

我覺得這是設計有點問題,也在咨詢gradle官方:http://forums.gradle.org/gradle/topics/call_plugin_extension_property_becomes_an_assignment

目前的workaround,還是基于gradle對extension的奇葩設計:
* 如果你的closure是定義在extension里面的,調用即賦值,掛
* 如果你的closure沒在extension定義中,而是在后面使用時加上去的,調用還是調用,ok
所有workaround就是把getCompileTimeJNI移出extension的定義,在外面加。

轉載于:https://www.cnblogs.com/baiyanhuang/p/3813469.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/376853.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/376853.shtml
英文地址,請注明出處:http://en.pswp.cn/news/376853.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OSGi.NET 學習筆記 [模塊化和插件化][小結]

【目錄】-【模塊化和插件化】-【小結】 現在我們來對OSGi.NET的“模塊化和插件化”做一個小結,再次把官方的說明拿出來  1) 物理隔離:基于UIOSP開發的模塊是一個物理隔離的可單獨部署的模塊,每一個模塊擁有獨立的文件夾、類型空…

miniob :相關環境配置

How to build 參考視頻:https://www.bilibili.com/video/BV1gv411A7oA?spm_id_from333.999.0.0將代碼下載并且安裝編譯。 git clone失敗的話參考:https://blog.csdn.net/sxg0205/article/details/81412921 install cmakebuild libevent git submodul…

Fedora 20 配置

前幾天裝了fedora 20, 斷斷續續的進行了以下配置: 1. 安裝oracle java及jdk版本切換 安裝的過程很簡單,從oracle官網上下載jdk及jre的rpm包,使用rpm -ivh 安裝。但是遇到一個問題,因為fedora系統自帶了openJDK,如果安裝oracle的jd…

raft算法學習(一):角色概念以及選舉過程

Raft算法是強領導模型,集群中只能有一個領導。 下面是raft的視頻講解: raft raft的三種角色及其概念 服務器節點狀態一共有三種:領導者(Leader)、跟隨著(Follower)、候選人(Candid…

解決 FLex 4.0 Module里面Alert.show();出錯問題

TypeError: Error #1009: 無法訪問空對象引用的屬性或方法。 at mx.managers::PopUpManagerImpl/http://www.adobe.com/2006/flex/mx/internal::createModalWindow()[E:\dev\hero_private\frameworks\projects\framework\src\mx\managers\PopUpManagerImpl.as:701] at mx.manag…

datetime2 數據類型

.net的Entity Framework構建網站數據層,給一個實體的DATETIME類型的屬性賦值時 突然莫名奇妙顯示有一個類型不匹配的異常如下: System.Data.SqlClient.SqlException: 從 datetime2 數據類型到 datetime 數據類型的轉換產生一個超出范圍的值。 解決方法&a…

Yslow的A評級指南

這里測的是V2引擎,V1想拿A幾乎不可能,一個CDN測試的F就可以輕松廢了你的網站。 A評級 現在一個一個分析。 User fewer HTTP Requests:減少HTTP請求 圖片、CSS、JS、flash等這些都需要增加http請求數,減少這些元素的數量能減少響應…

jquery下 選擇器整理

jQuery 的選擇器可謂之強大無比,這里簡單地總結一下常用的元素查找方法 $("#myELement") 選擇id值等于myElement的元素,id值不能重復在文檔中只能有一個id值是myElement所以得到的是唯一的元素 $("div") 選擇所有的di…

git日常使用教程

目錄git日常使用git 基礎用法(本地)git branchgit checkoutgit mergegit rebaseHEAD ,在提交樹上移動相對引用強制修改分支位置撤銷變更整理提交記錄提交技巧Git TagsGit Describegit 基礎用法(遠程)git fetchgit pullgit push偏離的提交歷史,十分重要!&…

android一鍵分享功能不使用任何第三方sdk

在android中有自帶的一鍵分享功能,不過它會把所有帶分享的應用都找出來,如果我們只需要一些常見的分享應用,該如何做呢? 下面看我的效果圖(橫屏和豎屏自動適配): 接下來看我的調用(支…

包含EditText組件的界面中,禁止自動彈出軟鍵盤

解決方法: 1)在Manifest.xml文件中相應的activity下添加一下代碼:android:windowSoftInputMode"stateHidden"2)讓EditText失去焦點,使用EditText的clearFocus方法 例如:EditText edit(EditText)f…

gcc 編譯器使用指南

目錄安裝準備test.cpp編譯g 編譯參數-g :編譯帶調試信息的可執行文件-O[n] :開啟優化-l 和 -L :指定庫文件 | 指定庫文件路徑-I :指定頭文件搜索目錄-Wall 和 -w:打印警告信息 | 關閉警告信息-stdc11 :設置…

bug found:定義對象時

看下面代碼 class Test{ }; class Test2{public:Test2(Test *t){}};int main(){Test test();//把定義一個對象 “Test test;” 寫成 “Test test();”函數聲明了!Test2 test2(&test);//return 0;}Dev-cpp的提示信息: no matching function for c…

CMake學習使用(基于vscode)

目錄語法一些重要指令CMake常用變量CMake編譯工程編譯流程兩種構建方式實例展示參考: 基于VSCode和CMake實現C/C開發 | Linux篇 語法 基本語法格式:指令(arg1 arg2 …) 參數使用括弧括起來參數之間使用空格或者分號分開 指令是大小寫無關的&#xff0…

idhttp.post方式 調用datasnap rest 遠程方法

idhttp.get方式調用,這種比較簡單,大家都會。post方式網上卻沒有任何成功的代碼,本人也是摸索了一個上午才搞定。 分享給大家。 (1)post方式調用的遠程方法,方法名必須加“update”前綴,不加行不…

[轉]連接excel數據源時,首行包含列名稱選項在連接字符串中的設置。

關于Excel導入的HDRYES; IMEX1詳解 ProviderMicrosoft.Jet.OLEDB.4.0;Data Source111.xls;Extended Properties"Excel 8.0;HDRNO"; 其中HDRNO或YES即首行包含列名稱選項 (參數HDR的值:HDRYes,這代表第一行是標題,不做為數據使用&am…

C++多線程快速入門(一):基本常用操作

目錄case1:創建線程1 join、detachcase2:創建線程2 線程傳參 傳值或者傳引用case3:創建線程 線程傳參 functional object作為參數case4:觀察多線程程序加速計算case5:future get 獲取并發結果case6:互斥鎖…

android:configChanges屬性總結

原文地址:http://blog.csdn.net/zhaokaiqiang1992/article/details/19921703 android中的組件Activity在manifest.xml文件中可以指定參數android:ConfigChanges,用于捕獲手機狀態的改變。 在Activity中添加了android:configChanges屬性&#…

eclipse 中修改 M2_REPO的值

從eclipse中增加了maven2的插件之后,maven默認的本地庫的路徑是${user}/.m2/repository/下,一般windows用戶的操作系統都安裝在C盤,所以這個目錄 下的jar包比較危險。我嘗試從myeclipse->preferences->java->build path->classpa…

C++多線程快速入門(二)共享數據同步以及數據競爭

目錄std::unique_lock類模板僅調用一次線程局部存儲原子變量往期內容回顧std::unique_lock類模板 互斥鎖保證了線程間的同步,卻將并行操作變成了串行操作,對性能有較大影響,所以我們要盡可能減小鎖的區間粒度。 lock_guard只能保證在析構的時…