2011-09-29 38 views
78

Tôi đang cố gắng hiểu thêm về java, đặc biệt là về quản lý bộ nhớ và chủ đề. Vì lý do này, gần đây tôi đã tìm thấy sự quan tâm đến việc xem xét các bãi chứa chuỗi.Làm cách nào để phân tích kết xuất chuỗi java?

Dưới đây là vài dòng trích từ một ứng dụng web sử dụng VisualVM, được xây dựng trong công cụ cho java:

"Finalizer" daemon prio=8 tid=0x02b3d000 nid=0x898 in Object.wait() [0x02d0f000] 
    java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    - waiting on <0x27ef0288> (a java.lang.ref.ReferenceQueue$Lock) 
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118) 
    - locked <0x27ef0288> (a java.lang.ref.ReferenceQueue$Lock) 
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134) 
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159) 

    Locked ownable synchronizers: 
    - None 

"Reference Handler" daemon prio=10 tid=0x02b3b800 nid=0x494 in Object.wait() [0x02cbf000] 
    java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    - waiting on <0x27ef0310> (a java.lang.ref.Reference$Lock) 
    at java.lang.Object.wait(Object.java:485) 
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116) 
    - locked <0x27ef0310> (a java.lang.ref.Reference$Lock) 

Trước tiên tôi có thắc mắc về một số tên biến:

  • những gì hiện tid và nid có nghĩa là gì?
  • Hình trong ngoặc đơn vuông sau Object.wait là gì?

Sau đó cho chồng theo dõi bản thân:

  • có nghĩa gì chờ đợi vào < .....> (a java.lang ....) và số lượng là những gì trong < ..>
  • có nghĩa gì khóa < .....> (a java.lang ....) cùng một câu hỏi, những gì trong < ..>

Tôi nghĩ từ khóa bị khóa liên quan đến điều kiện chờ đợi, tuy nhiên, tôi đã sai. Trong thực tế, tôi tự hỏi tại sao khóa được lặp lại ba lần, nhưng các chủ đề ở trạng thái Runnable như đã thấy trong cùng một bãi:

"Thread-0" prio=6 tid=0x02ee3800 nid=0xc1c runnable [0x03eaf000] 
    java.lang.Thread.State: RUNNABLE 
    at java.io.FileInputStream.readBytes(Native Method) 
    at java.io.FileInputStream.read(FileInputStream.java:199) 
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:256) 
    at java.io.BufferedInputStream.read(BufferedInputStream.java:317) 
    - locked <0x23963378> (a java.io.BufferedInputStream) 
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264) 
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306) 
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158) 
    - locked <0x23968450> (a java.io.InputStreamReader) 
    at java.io.InputStreamReader.read(InputStreamReader.java:167) 
    at java.io.BufferedReader.fill(BufferedReader.java:136) 
    at java.io.BufferedReader.readLine(BufferedReader.java:299) 
    - locked <0x23968450> (a java.io.InputStreamReader) 
    at java.io.BufferedReader.readLine(BufferedReader.java:362) 
    at org.codehaus.plexus.util.cli.StreamPumper.run(StreamPumper.java:145) 

Rồi cuối cùng của tất cả, đây là điều tồi tệ nhất trong số họ:

"CompilerThread0" daemon prio=10 tid=0x02b81000 nid=0x698 waiting on condition [0x00000000] 
    java.lang.Thread.State: RUNNABLE 

Chủ đề này ở trạng thái runnable, nhưng nó đang chờ trong điều kiện. Điều kiện gì và 0x00000 là gì?

Tại sao dấu vết ngăn xếp quá ngắn mà không có bất kỳ bằng chứng nào về lớp chuỗi?

Nếu bạn có thể trả lời cho tất cả các câu hỏi của tôi, tôi sẽ rất biết ơn.

Cảm ơn

Trả lời

100

TID là id thead và NID là: ID chủ đề gốc. ID này phụ thuộc nhiều vào nền tảng. Đó là NID trong jstack thread dumps. Trên Windows, nó chỉ đơn giản là ID luồng cấp hệ điều hành trong một tiến trình. Trên Linux và Solaris, đó là PID của thread (mà lần lượt là một quá trình trọng lượng nhẹ). Trên Mac OS X, nó được gọi là giá trị pthread_t gốc.

Đi tới liên kết này: Java-level thread ID: để biết định nghĩa và giải thích thêm về hai thuật ngữ này.

Trên trang web của IBM, tôi tìm thấy liên kết này: How to interpret a thread dump. bao gồm chi tiết hơn:

Điều này giải thích điều chờ đợi trên phương tiện: Khóa ngăn nhiều hơn một thực thể truy cập tài nguyên được chia sẻ. Mỗi đối tượng trong Java ™ có khóa liên quan (thu được bằng cách sử dụng khối hoặc phương thức được đồng bộ hóa). Trong trường hợp của JVM, các luồng cạnh tranh với các tài nguyên khác nhau trong JVM và khóa trên các đối tượng Java.

Sau đó, nó mô tả màn hình dưới dạng một loại khóa đặc biệt được sử dụng trong JVM để cho phép đồng bộ hóa linh hoạt giữa các luồng. Với mục đích của phần này, hãy đọc các điều khoản theo dõi và khóa thay thế cho nhau.

Sau đó, nó còn đi xa hơn:

Để tránh việc có một màn hình trên tất cả các đối tượng, các JVM thường sử dụng một lá cờ trong một lớp học hoặc phương pháp khối để cho biết rằng mục bị khóa. Hầu hết thời gian, một đoạn mã sẽ chuyển một số phần bị khóa mà không tranh chấp. Do đó, lá cờ người giám hộ là đủ để bảo vệ đoạn mã này. Đây được gọi là màn hình phẳng. Tuy nhiên, nếu một chuỗi khác muốn truy cập một số mã bị khóa, một tranh chấp chính hãng đã xảy ra. JVM bây giờ phải tạo (hoặc thổi phồng) đối tượng màn hình để giữ luồng thứ hai và sắp xếp cho một cơ chế báo hiệu để điều phối truy cập vào phần mã. Màn hình này bây giờ được gọi là một màn hình tăng cao.

Dưới đây là giải thích chi tiết hơn về những gì bạn thấy trên các dòng từ kết xuất chuỗi. Một luồng Java được thực hiện bởi một chuỗi gốc của hệ điều hành. Mỗi chủ đề được đại diện bởi một dòng in đậm như:

"Thread-1" (TID: 0x9017A0, sys_thread_t: 0x23EAC8, tiểu bang: R, ID mẹ đẻ: 0x6E4) PRIO = 5

* Các sau 6 hạng mục giải thích điều này như tôi đã xuất hiện chúng từ ví dụ này, các giá trị trong ngoặc []:

  1. tên [TID: 0x9017A0],
  2. định danh [sys_thread_t],
  3. JVM địa chỉ cấu trúc dữ liệu [0x23EAC8],
  4. tình trạng hiện thời [nhà nước: R],
  5. có nguồn gốc chủ đề định danh [0x6E4],
  6. và ưu tiên [PRIO = 5] .

"wait on" dường như là một chuỗi daemon liên kết với chính jvm chứ không phải là chuỗi ứng dụng perse. Khi bạn nhận được một "trong Object.wait()", điều đó có nghĩa là chuỗi daemon, "finalizer" ở đây, đang chờ thông báo về một khóa trên một đối tượng, trong trường hợp này nó hiển thị cho bạn thông báo nào đang chờ trên: " - chờ đợi vào < 0x27ef0288> (a java.lang.ref.ReferenceQueue $ Lock)"

Định nghĩa về ReferenceQueue là: hàng đợi tham khảo, mà đăng ký đối tượng tham chiếu được nối bởi các nhà sưu tập rác sau khi thay đổi reachability thích hợp được phát hiện.

Chuỗi kết thúc chạy để bộ sưu tập rác hoạt động để làm sạch tài nguyên được liên kết với đối tượng. Nếu tôi nhìn thấy nó một cách cẩn thận, finalizer không thể lấy khóa cho đối tượng này: java.lang.ref.ReferenceQueue.remove (ReferenceQueue.java:118) vì đối tượng java đang chạy một phương thức, do đó, luồng finalizer là bị khóa cho đến khi đối tượng đó kết thúc với nhiệm vụ hiện tại của nó.

Ngoài ra, trình hoàn thiện không chỉ tìm cách lấy lại bộ nhớ, nó còn liên quan nhiều hơn để dọn dẹp tài nguyên. Tôi cần phải nghiên cứu thêm về nó, nhưng nếu bạn có tập tin mở, ổ cắm, vv ... liên quan đến một phương pháp đối tượng, sau đó finalizer sẽ làm việc trên giải phóng những mặt hàng lên là tốt.

Hình trong ngoặc đơn vuông sau đối tượng Object.wait trong trường hợp kết xuất chuỗi là gì?

Đây là con trỏ trong bộ nhớ cho chuỗi. Dưới đây là một mô tả chi tiết hơn:

Thông tin C.4.1 Chủ đề

Phần đầu của bộ phận chủ đề thể hiện chủ đề đó gây ra lỗi nghiêm trọng, như sau:

Current thread (0x0805ac88): JavaThread "main" [_thread_in_native, id=21139] 
        |    |   |   |   +-- ID 
        |    |   |   +------------- state 
        |    |   +-------------------------- name 
        |    +------------------------------------ type 
        +-------------------------------------------------- pointer 

Con trỏ thread con trỏ đến cấu trúc chuỗi nội bộ Java VM. Nó thường không quan tâm trừ khi bạn đang gỡ lỗi một máy ảo Java hoặc tệp lõi.

mô tả cuối cùng này đến từ: Troubleshooting Guide for Java SE 6 with HotSpot VM

Dưới đây là một số liên kết về chủ đề bãi:

6

Tiếp tục câu trả lời tuyệt vời @ James Drinkard của:

Lưu ý rằng, tùy thuộc vào việc thực hiện cơ bản, các java.lang.Thread.State của một thread mà bị chặn trong một phương pháp tự nhiên có thể được báo cáo là RUNNABLE, nơi A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.

Nó chỉ ra rằng mô tả này cũng bao gồm bị chặn trong cuộc gọi hệ điều hành như cuộc thăm dò ý kiến ​​hoặc hoạt động đọc - có lẽ vì không đảm bảo rằng JVM có thể biết khi nào cuộc gọi phương thức gốc đã bị chặn ở cấp hệ điều hành.

Nhiều cuộc thảo luận về các luồng đề tài JVM mà tôi đã bỏ qua hoặc bỏ qua nó mà không xem xét các ý nghĩa - không ít nhất là các công cụ giám sát có thể báo cáo nhầm lẫn rằng một số chủ đề như vậy đang 'chạy' và hơn nữa, tất cả đều chạy ở mức 100%.

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