首頁>技術>

infer 是facebook 出品的程式碼靜態檢查工具,這個工具中的racerd是可以用來檢查java 執行緒中的data race問題。

執行方式

檢查單個的java檔案

infer --racerd-only -- javac File.java

檢查android的專案

./gradlew clean #清除編譯結果,方便檢查所有的結果

infer --racerd-only -- ./gradlew build

檢查出來的結果

比如下面的程式碼

@ThreadSafe

class Publisher implements Runnable {

private ConnectionFactory factory = new ConnectionFactory();

private Channel channel;

private Queue<String> queue = new LinkedList<String>();

private boolean isInited;

public void init() {

if(isInited) {

return;

}

.........

}

@Override

public void run() {

init();

while(true) {

查下來log 如下

app/src/main/java/com/example/systeminfo/ui/notifications/NotificationsFragment.java:77: warning: THREAD_SAFETY_VIOLATION

Read/Write race. Non-private method `void NotificationsFragment$Publisher.init()` reads without synchronization from `this.isInited`. Potentially races with write in method `NotificationsFragment$Publisher.init()`.

Reporting because the current class is annotated `@ThreadSafe`, so we assume that this method can run in parallel with other non-private methods in the class (including itself).

75.

76. public void init() {

77. > if(isInited) {

78. return;

79. }

app/src/main/java/com/example/systeminfo/ui/notifications/NotificationsFragment.java:84: warning: THREAD_SAFETY_VIOLATION

Unprotected write. Non-private method `void NotificationsFragment$Publisher.init()` writes to field `this.isInited` outside of synchronization.

Reporting because the current class is annotated `@ThreadSafe`, so we assume that this method can run in parallel with other non-private methods in the class (including itself).

82. Connection conn = factory.newConnection();

83. channel = conn.createChannel();

84. > isInited = true;

85. } catch (URISyntaxException e) {

86. e.printStackTrace();

app/src/main/java/com/example/systeminfo/ui/notifications/NotificationsFragment.java:83: warning: THREAD_SAFETY_VIOLATION

Unprotected write. Non-private method `void NotificationsFragment$Publisher.init()` writes to field `this.channel` outside of synchronization.

Reporting because the current class is annotated `@ThreadSafe`, so we assume that this method can run in parallel with other non-private methods in the class (including itself).

81. factory.setUri("amqp://user:[email protected]:5672/%2f");

82. Connection conn = factory.newConnection();

83. > channel = conn.createChannel();

84. isInited = true;

85. } catch (URISyntaxException e) {

發現init函式裡面有個isInited 可能不是執行緒安全的,實際上init函式並不會在run以外被呼叫,但是由於是介面是public的有可能被人誤用了,安全的做法就是把這個介面改成private的

infer 檢查如何起作用

infer的RacerD 檢查並不是自然發生的,需要滿足兩個條件

(1)用@ThreadSafe顯式註解一個類/方法;

(2)通過synchronized關鍵字使用鎖。

在這兩種情況下,RacerD會在包含訊號及其所有依賴的程式碼中尋找併發問題。特別是,它將報告同一類的任何非私有方法之間的競合,這些方法可能出現訪問衝突。用@ThreadSafe註釋一個類/介面,也會觸發對該類/介面的所有子類/實現的檢查。

infer 還有其他的一些註解也會觸發檢查,如 GuardBy等

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 基於Spring Boot為美柚大資料研發的大資料任務排程平臺原始碼分享