2009-08-28 46 views
15

Tôi đang tìm cách bao gồm __LINE__ dưới dạng hằng số biên dịch trong các thư đã xuất.__LINE__ tương đương với Java?

Các giải pháp khác nhau dường như tồn tại, nhưng với hình phạt thời gian chạy lớn như được đề xuất trong __LINE__ in JS__LINE__ in C#. Chúng thường dựa trên một đối tượng thời gian chạy là StackFrame là log4j.

Sử dụng khả năng bật/tắt log4j trên cơ sở cần thiết không phải là tùy chọn vì thường khi xảy ra lỗi, quá muộn để bật số dòng và mã nội tuyến dường như không có bất kỳ số dòng nào nữa không. . nó sẽ có thể để một trong hai:

  1. Pre-quá trình các file nguồn java trước khi biên dịch, lý tưởng với một cái gì đó tích hợp với Eclipse , vì vậy nó có thể được thử nghiệm trên nền tảng developpement cũng có.
  2. Có thể trước khi xử lý lớp lúc tải. Chi phí đầu vào sau đó sẽ không đáng kể bằng cách khấu hao.

1. Trên thực tế tôi sử dụng một hack xấu xí: gọi một tiền xử lý tùy chỉnh ngay sau khi kiểm tra trên máy chủ xây dựng thông qua thủ đoạn ANT

+0

Chỉ vì sự tò mò của tôi: Tại sao bạn cần số dòng trong nhật ký? Khi một lỗi xảy ra, bạn có stacktrace hoàn chỉnh, cho biết số dòng ... – romaintaz

+3

Đôi khi trong trường hợp ngoại lệ, thay vì số dòng tôi có một cái gì đó như 'Util.java (Inlined Compiled Code)'. Và đôi khi tôi không có bất kỳ ngoại lệ nào, chỉ cần đăng nhập thông tin: "ở đây", "ở đây", tôi không muốn bận tâm khi có thông báo duy nhất (số dòng làm cho chúng độc đáo) –

+0

JVM sẽ có thể xử lý tình huống đó. Bạn sử dụng phiên bản Java nào? –

Trả lời

8

Nếu bạn biên dịch với các tùy chọn debug=line, thông tin đường tồn tại trong tập tin lớp nhưng VM có thể ném mà đi trong thời gian chạy . Điều này phụ thuộc vào một số tùy chọn mà bạn có thể chỉ định khi bạn khởi động chương trình Java. Thông thường, hiệu suất phạt cho chạy với gỡ lỗi infos là khoảng 5% cộng với bộ nhớ nhiều hơn một chút trong không gian gen perm. Vì thông tin này vô giá, tôi không thấy lý do gì để loại bỏ thông tin này.

Nhận xét của bạn (Util.java(Inlined Compiled Code)) khuyên bạn nên sử dụng tối ưu hóa tích cực. Nếu bạn có thể, hãy tắt chúng đi. Bằng cách đó, bạn có thể chỉ đơn giản là:

// For Java 1.4, use new Exception().getStackTrace() 
int line = Thread.currentThread().getStackTrace()[0].getLineNumber(); 

khi bạn cần đến nó (ví dụ: bên trong catch hoặc if (log.isInfoEnabled())).

Đối với __LINE__, trình biên dịch Java không có hỗ trợ cho việc này. Lựa chọn duy nhất của bạn là sử dụng một số hacks để lọc nguồn. Tôi đề nghị để xác định một biến int __LINE__ một nơi nào đó và thiết lập cho một số giá trị ngẫu nhiên (0 là ngẫu nhiên đủ) khi bạn cần nó. Sau đó viết bộ lọc thay thế số trong __LINE__ = \d+ bằng số dòng hiện tại. Điều này cho phép sửa số dòng tại chỗ.

+0

Tại sao 'new Exception(). GetStackTrace()' thay vì 'Thread.currentThread(). GetStackTrace()'? –

+0

Không có lý do gì nhưng thực tế là tôi không bận tâm tìm kiếm lớp Thread để biết cách lấy stack hiện tại và tôi biết rằng Exception có nó :) –

+0

+1 cho một giải pháp có thể được sử dụng trên môi trường dev của tôi (chỉ tìm kiếm và thay thế 'Thread ....' bằng số dòng trong quá trình xây dựng) –

13

Đó là không thể có được ảnh hưởng của __LINE__ trong C mà xảy ra lúc biên dịch thời gian.

Bạn có thể nhận được số dòng bằng cách gọi một hàm như thế này trong thời gian chạy,

public static int lineNumber() { 
    return Thread.currentThread().getStackTrace()[2].getLineNumber(); 
} 
+2

Thông tin gỡ lỗi về dòng phải được biên dịch vào tệp lớp, để truy cập thông tin này. – Mnementh

0

Tôi không nghĩ Java cung cấp những gì bạn cần.

Tuy nhiên, nếu bạn viết bộ xử lý chú thích của riêng mình và sử dụng Java 6.0 compiler APIs Tôi nghĩ bạn có thể giải quyết vấn đề này. Tôi sẽ không quan tâm để đoán bao nhiêu công việc nó sẽ được để làm như vậy.

Lưu ý rằng Eclipse cho phép bạn bao gồm việc xử lý chú thích của riêng bạn trong cơ chế xây dựng của nó.

0

Tôi không biết về một thứ như vậy trong trình biên dịch Java. Nhưng bạn có thể viết một chương trình đơn giản, thay thế một mã thông báo như __LINE__ bằng linenumber trong tệp và định cấu hình buildprocess của bạn để thực thi công cụ này trước khi biên dịch. Một số loại tiền xử lý.

+0

Đó chính xác là những gì tôi muốn thay thế (xem chú thích cuối trang 1.) –

1

Tôi sẽ sử dụng khung ghi nhật ký cho việc này và để nó xử lý các chi tiết lộn xộn. Cả hai java.util.logging và logback có thể dễ dàng hiển thị thông tin về người gọi tương tự như những gì LINE có thể cung cấp.

Lợi ích chính là thông tin chỉ được tính nếu cần thiết, vì vậy không xuất ra có nghĩa là không có phí.

5

Đúng là ra khỏi hộp, các macro này không khả dụng. Tuy nhiên, bằng cách sử dụng thiết bị đo đạc và gỡ lỗi thông tin, bạn có thể thực hiện nó. kiểm tra http://www.gallot.be/?p=85

4

Tôi đã tìm thấy lớp học này giúp mọi thứ trở nên dễ dàng nếu bạn đang tìm kiếm "đã đến đây, đã đến đây" nhập nhật ký. Tôi có một Here.java tập tin mà tôi thêm vào dự án của tôi có chứa chỉ định nghĩa lớp sau đây:

public class Here { 
    public static String at() { 
     StackTraceElement ste = Thread.currentThread().getStackTrace()[3]; 
     String where = ste.getClassName() + " " + ste.getMethodName() + " " + ste.getLineNumber() + " "; 
     return where; 
    } 
} 

Để sử dụng nó trong dạng đơn giản nhất:

Log.v(TAG, Here.At()); 

Hoặc, nếu bạn muốn xem công cụ khác:

Log.v(TAG, Here.At() + String.format("interesting value = %d", my_val)); 

này sẽ cung cấp cho "com.otherpackagenamestuff.MyClass myMethod 225" trong trường hợp đầu tiên, và giống nhau nhưng với "giá trị thú vị = 123" nối trong trường hợp thứ hai.

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