2014-04-02 34 views
4

調查和接受答案的詳細信息在問題的評論中。DateTime compareTo不適用於DateTime

我有一個小型的Java項目,它讀取一個調度並將Joda時間間隔放入一個有序的映射(本例中爲TreeMap)以供進一步處理。 這是通過ScheduledExecutorService的完成:

executor.scheduleWithFixedDelay(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       doWork(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
       throw new RuntimeException(e); 
      } 
     } 
    }, 1, 1, TimeUnit.SECONDS); 

doWork()然後讀取的文件時,產生了一些時間間隔,然後填充使用此比較的地圖(地圖構造函數中指定):

@Override 
public int compare(Interval o1, Interval o2) { 
    return o1.getStart().compareTo(o2.getStart()); 
} 

然後,該代碼插入第一個時間間隔時會在比較器中斷開。 通常我會覺得有什麼不對的間隔本身,但是我已經檢查了幾種可能性,並注意到我迷路了多奇怪的事情:

  • 的間隔很好,o1o2與有效DateTime是否相同的長時間戳。
  • 沒有發現任何異常。線程停止工作。
  • 當我從Eclipse啓動應用程序時,一切正常。它只在啓動部署版本時中斷。通過部署,我的意思是它被打包成一個.jar並複製到共享目錄,這裏沒有容器。
  • 更改

    try { 
        doWork(); 
    } catch (Exception e) { 
        e.printStackTrace(); 
        throw new RuntimeException(e); 
    } 
    

    try { 
        doWork(); 
    } catch (Throwable e) { 
        e.printStackTrace(); 
        throw new RuntimeException(e); 
    } 
    

    修復它。 (即地圖填充得很好,包括原始的第一個間隔)。

最後一部分讓我覺得這是一個JIT或JVM的錯誤,而不是代碼。 我也探討過這個正在構建問題的可能性,但它似乎並沒有這樣的情況:

  • Eclipse和構建服務器使用的Java 7(Eclipse的7.0.51,構建服務器:7.0。 25,使用7.0.51 JRE啓動已部署的版本
  • Joda時間庫版本與Eclipse和部署的lib文件夾(2.1)相同
  • 這不是一個新功能,而且代碼非常相似不同的分支,現在已經有幾個星期了
  • 我試着停止使用自己的緩存常春藤庫的Eclipse,而是使用t他在部署的目錄中存儲庫。相同的東西 - 來自Eclipse的作品在使用Java啓動jar時不起作用。

後一點遠程調試我已再現等的東西:Method "compareTo" with signature "(Lorg/joda/time/ReadableInstant;)I" is not applicable on this object與目標對象在比較代碼設置斷點時是class org.joda.time.DateTime

任何有關如何進一步調試的幫助,將不勝感激。

編輯:

private void doWork() { 
     SortedMap<Interval, String> map = new TreeMap<>(new Comparator<Interval>() { 
      @Override 
      public int compare(Interval o1, Interval o2) { 
       return o1.getStart().compareTo(o2.getStart()); 
      } 
     }); 

     Collection<String> col1 = new HashSet<>(); 
     Collection<String> col2 = new HashSet<>(); 
     String string = ""; 
     long ts = 0; 

     try (FileInputStream input = new FileInputStream(fileName); 
       InputStreamReader isr = new InputStreamReader(input); 
       BufferedReader reader = new BufferedReader(isr)) { 
      String line = reader.readLine(); 
      map.put(new Interval(new DateTime(), new DateTime()), ""); 
     } 
} 

雖然這看起來並不像一個SSCCE由於很多額外的代碼,如果我刪除了收集的聲明或讀行,或之前把任何東西在地圖上嘗試阻止(然後按原樣完成) - 一切正常。讓我想到競態條件,但是這裏涉及的所有變量都是本地的(除了fileName,它保證已經設置)。

此外,雖然嘗試的東西,我發現從2.1切換到喬達時間2.3顯然解決了這個問題。然而,我沒有看到他們的更新日誌中的任何東西,甚至遠程相關。

+0

這可能是有益的,如果我們可以看到'doWork()'的定義。另外,當你說「部署」時,你的意思是什麼?你在容器中運行這個嗎? –

+0

感謝您的格式編輯。通過部署我的意思是它被打包成一個罐子,並複製到一個遠程驅動器,沒有容器或網絡服務器(我意識到我們在這裏使用這個術語很不一樣)。 – Ordous

+0

此外,它似乎是否重現錯誤取決於一些不明確的因素,如額外的進口或揮發性或變量未在線程中使用(但在同一類中聲明) – Ordous

回答

1

這裏對我的意見基地總結答案:

是否遠程端有第二JodaTime版本?也許是版本2.0之前的Comparable處理髮生了一些變化的舊版本(請參閱Generified接口ReadableInstant)? Pre 2.0有問題的方法有簽名compareTo(Object)而2.0和更高版本新簽名compareTo(ReadableInstant),也請參閱release notes。這種兩個joda-jar和一個連接類加載問題的情況將解釋以下異常消息:

帶簽名的方法「compareTo」(Lorg/joda/time/ReadableInstant;)I「不適用於此對象目標對象是類org.joda.time.DateTime

(你的問題非常棘手,並已當之無愧更upvotes。很高興聽到你找到了JRuby的庫中包含的舊JodaTime版本的原因。)