2008-09-25 30 views
17

Nếu bạn có hai lọ trong đường dẫn lớp có chứa các phiên bản khác nhau của cùng một lớp, thứ tự classpath trở nên quan trọng.Có công cụ nào để khám phá xem cùng một lớp có tồn tại trong nhiều lọ trong classpath không?

Tôi đang tìm một công cụ có thể phát hiện và gắn cờ các xung đột tiềm năng đó trong một đường dẫn lớp hoặc tập hợp các thư mục nhất định.

Chắc chắn một kịch bản mà bắt đầu:

classes=`mktemp` 
for i in `find . -name "*.jar"` 
do 
    echo "File: $i" > $classes 
    jar tf $i > $classes 
    ... 
done 

với một số loại thông minh/uniq/diff/grep/AWK sau này có tiềm năng, nhưng tôi đã tự hỏi nếu có ai biết của bất kỳ giải pháp hiện có.

Trả lời

6

Công cụ Tattletale từ JBoss là ứng cử viên khác: "Spot nếu một lớp/gói nằm trong nhiều tập tin JAR"

+0

Hãy thử jarfish cũng (câu trả lời khác của tôi); Tôi đã sử dụng thành công –

+0

Yup! Hoặc điều này hoặc http://stackoverflow.com/questions/135971/is-there-a-tool-to-discover-if-the-same-class-exists-in-multiple-jars-in-the-clas/4516827 # 4516827 nên làm các trick! –

+0

Có công cụ/cách nào chỉ lọc các lớp được sử dụng (đã nhập) không? Chúng tôi có rất nhiều lớp học trùng lặp trong classpath của chúng tôi mà thực sự không bao giờ được sử dụng –

1
+0

Cả hai xuất hiện để làm điều ngược lại với những gì tôi muốn: họ tìm thấy một lớp nhất định trong một bộ lọ. Tôi muốn tìm các lớp xung đột trong một classpath đã cho hoặc tập hợp các lọ. –

+0

Theo cách ngược lại thì sao? Họ liệt kê những JAR nào có thể tìm thấy, và nếu có nhiều kết quả trùng khớp, chúng sẽ liệt kê tất cả chúng - đó là danh sách xung đột của bạn. – skaffman

+0

Nhưng tôi muốn khám phá mọi trường hợp của một số lớp xuất hiện trong nhiều lọ. Tôi sẽ phải chạy whichj cho mỗi lớp trong CLASSPATH của tôi và tìm kiếm các bản sao (sắp xếp | uniq | diff) - chỉ là một phiên bản chậm hơn của đề xuất brute-force của tôi trong câu hỏi. –

4

Tôi nghĩ rằng nó sẽ không quá khó để viết một công cụ để tự của bạn.

Bạn có thể nhận các mục nhập classpath bằng System.getProperty ("java.class.path");

Và sau đó đi bộ qua các lọ, khóa hoặc các thư mục được liệt kê ở đó và thu thập tất cả thông tin về các lớp và tìm ra những thông tin có thể gây ra sự cố.

Nhiệm vụ này sẽ mất tối đa 1 hoặc 2 ngày. Sau đó, bạn có thể tải lớp này trực tiếp trong ứng dụng của mình và tạo báo cáo.

Có lẽ thuộc tính java.class.path sẽ không hiển thị tất cả các lớp nếu bạn chạy trong một số cơ sở hạ tầng với tải lớp tùy chỉnh phức tạp (ví dụ: tôi đã từng thấy ứng dụng tải các lớp từ LDAP) nhưng nó chắc chắn sẽ hoạt động tốt nhất của các trường hợp.

Là một công cụ bạn có thể thấy hữu ích, tôi chưa bao giờ sử dụng nó, nhưng hãy thử và cho chúng tôi biết kết quả.

http://www.jgoodies.com/freeware/jpathreport/features.html

Nếu bạn đang đi để tạo ra công cụ của riêng bạn, đây là đoạn code tôi sử dụng cho các kịch bản shell cùng gửi trước đó, nhưng mà tôi sử dụng trên máy tính Windows của tôi. Nó chạy nhanh hơn khi có tấn tệp jar.

Bạn có thể sử dụng và sửa đổi nó để thay vì đệ quy đi bộ thư mục, đọc đường dẫn lớp và so sánh thuộc tính thời gian .class.

Có một lớp học chỉ huy bạn có thể phân lớp nếu cần thiết, tôi đã suy nghĩ trong tùy chọn -execute của "tìm"

này mã của riêng tôi, vì vậy nó đã không có ý định "sản xuất sẵn sàng", chỉ để làm việc.

import java.io.*; 
import java.util.zip.*; 


public class ListZipContent{ 
    public static void main(String [] args) throws IOException { 
     System.out.println("start " + new java.util.Date()); 
     String pattern = args.length == 1 ? args[0] : "OracleDriver.class";// Guess which class I was looking for :) 
     File file = new File("."); 
     FileFilter fileFilter = new FileFilter(){ 
      public boolean accept(File file){ 
       return file.isDirectory() || file.getName().endsWith("jar"); 
      } 
     }; 
     Command command = new Command(pattern); 
     executeRecursively(command, file, fileFilter); 
     System.out.println("finish " + new java.util.Date()); 
    } 
    private static void executeRecursively(Command command, File dir , FileFilter filter) throws IOException { 
     if(!dir.isDirectory()){ 
      System.out.println("not a directory " + dir); 
      return; 
     } 
     for(File file : dir.listFiles(filter)){ 
      if(file.isDirectory()){ 
       executeRecursively(command,file , filter); 
      }else{ 
       command.executeOn(file); 
      } 
     } 
    } 
} 
class Command { 

    private String pattern; 
    public Command(String pattern){ 
     this.pattern = pattern; 
    } 

    public void executeOn(File file) throws IOException { 
     if(pattern == null) { 
      System.out.println("Pattern is null "); 
      return; 
     } 

     String fileName = file.getName(); 
     boolean jarNameAlreadyPrinted = false; 

     ZipInputStream zis = null; 
     try{ 
      zis = new ZipInputStream(new FileInputStream(file)); 

      ZipEntry ze; 
      while((ze = zis.getNextEntry()) != null) { 
       if(ze.getName().endsWith(pattern)){ 
        if(!jarNameAlreadyPrinted){ 
         System.out.println("Contents of: " + file.getCanonicalPath() ); 
         jarNameAlreadyPrinted = true; 
        } 
        System.out.println(" " + ze.getName()); 
       } 
       zis.closeEntry(); 
      } 
     }finally{ 
      if(zis != null) try { 
       zis.close(); 
      }catch(Throwable t){} 
     } 
    } 
} 

Tôi hy vọng điều này sẽ hữu ích.

+2

lý do tại sao bạn sẽ dành 1 hoặc 2 ngày khi có khả năng công cụ sẽ làm điều đó cho bạn? Nếu bạn không làm việc trên dự án của bạn direcetly trong 1 hoặc 2 ngày nó tốt hơn là một sở thích hoặc bạn đang làm điều gì đó sai trái. – ArtB

+0

Liên kết http://www.jgoodies.com/freeware/jpathreport/features.html đã chết. Bạn có thể vui lòng cập nhật nó? –

0

jarclassfinder là một nhật thực cắm tùy chọn

+0

Mô tả của sản phẩm nói rằng đó là một "tiện ích bổ sung cho việc tìm kiếm các tệp Java Archive (JAR) chứa một lớp đã cho cho đường dẫn xây dựng Java của một dự án." Điều này trái ngược với những gì tôi cần. Tôi cần phải biết nếu cùng một lớp là trong hai lọ, KHÔNG jar mà một lớp nhất định là in –

+1

Nó sẽ phát hiện ra rằng một lớp nhất định là trong nhiều lọ, nhưng nó sẽ không tìm thấy tất cả các trường hợp của các lớp trong nhiều lọ. –

8

Hình như jarfish sẽ làm những gì bạn muốn với "giá trị nhân bản" lệnh của nó.

+0

Rất tuyệt! Hoặc điều này hoặc http://stackoverflow.com/questions/135971/is-there-a-tool-to-discover-if-the-same-class-exists-in-multiple-jars-in-the-clas/4523559 # 4523559 nên làm các trick. –

+0

Điều này đã hiệu quả. Tôi không nghĩ rằng Tattletale xử lý các tệp jar rất tốt. Nếu có, tôi không hiểu. –

0

Nếu bạn không thích tải về và cài đặt công cụ bạn có thể sử dụng lệnh một dòng này để tìm xung đột jar với công cụ gnu tiêu chuẩn. Nó là thô sơ nhưng bạn có thể mở rộng nó như bạn sẽ.

ls *.jar | xargs -n1 -iFILE unzip -l FILE | grep class | sed "s,.* ,," | tr "/" "." | sort | uniq -d | xargs -n1 -iCLASS grep -l CLASS *.jar | sort -u 

(nó là một chút chậm chạp trong việc chạy nếu bạn có rất nhiều lọ)

Giải thích: Nó liệt kê tất cả các tập tin trong tất cả các lọ, greps cho các file lớp, thấy giá trị nhân bản, sau đó greps các lọ gốc để xem chúng xuất hiện ở đâu. Nó có thể được thực hiện hiệu quả hơn với một kịch bản phức tạp hơn.

Các vấn đề liên quan