2012-05-02 38 views
16

Có bất kỳ cách sử dụng thực tế nào của mã mở khóa NOP của Máy ảo Java trong JVM ngày nay không? Nếu vậy, một số kịch bản trong đó NOP s sẽ được tạo ra trong bytecode là gì?NOP trong bytecode JVM được sử dụng cho là gì?

Tôi thậm chí còn muốn xem ví dụ về mã Java biên dịch thành bytecode với NOP s.


Cập nhật

lớp MethodGen BCEL cho biết,

Trong khi tạo mã nó có thể cần thiết để chèn các hoạt động NOP.

Tôi đoán các thư viện thế hệ Bytecode khác nằm trong cùng một thuyền, như đã được chỉ ra trong câu trả lời được chấp nhận.

+0

Thông thường nó được sử dụng trong mã gỡ lỗi để cho phép các điểm ngắt trên thứ không dịch sang bytecode, như '{'. – vcsjones

+0

Bạn có nghĩa là điều này sẽ xuất hiện trong bytecode khi một tệp Java được biên dịch với 'javac -g'? – jbranchaud

+0

Tôi không tin rằng 'javac' sẽ làm điều đó. Nhưng các trình biên dịch và trình gỡ rối khác có thể sử dụng chức năng đó. – vcsjones

Trả lời

12

Một số trường hợp sử dụng NOP bytecode là dành cho biến đổi class tập tin, tối ưu hóa và phân tích tĩnh được thực hiện bởi các công cụ như Apache BCEL, ASM, FindBugs, PMD, vv Apache BCEL manual chạm vào một số công dụng của NOP để phân tích và tối ưu hóa mục đích .

Một JVM có thể sử dụng NOP bytecode để tối ưu hóa JIT để đảm bảo các khối mã đang được đồng bộ hóa an toàn được căn chỉnh phù hợp để tránh false sharing.

Đối với một số mã mẫu được biên dịch bằng trình biên dịch JDK javac có chứa NOP bytecodes, đó là một thử thách thú vị. Tuy nhiên, tôi nghi ngờ trình biên dịch sẽ tạo ra bất kỳ tệp class nào chứa NOP bytecodes từ the bytecode instruction stream is only single-byte aligned. Tôi sẽ tò mò muốn xem một ví dụ như vậy, nhưng tôi không thể tự nghĩ ra được.

1

Không có ops nào được thêm vào để tối ưu hóa đường ống xử lý. Tôi không chắc Java hiện đang sử dụng chúng ở mức độ nào.

Từ Wikipedia:

Một NOP thường được sử dụng cho các mục đích thời gian, để buộc liên kết bộ nhớ , để ngăn chặn các mối nguy hiểm, để chiếm một khe chậm trễ chi nhánh, hoặc như là một địa giữ phải được thay thế bằng cách hướng dẫn hoạt động sau này trong chương trình phát triển chương trình (hoặc để thay thế các hướng dẫn bị loại bỏ khi tái cấu trúc sẽ có vấn đề hoặc tốn thời gian). Trong một số trường hợp, NOP có thể có các tác dụng phụ nhỏ là ; ví dụ, trên bộ xử lý Motorola 68000, mã hóa NOP gây ra sự đồng bộ hóa của đường ống.

+6

Điều này có ý nghĩa trong một opcode máy vật lý, nhưng điều gì sẽ là việc sử dụng một thứ như vậy cho một opcode * máy ảo *? –

+0

Tôi đánh giá cao câu trả lời, nhưng câu hỏi này rất cụ thể về JVM. – jbranchaud

2

Dưới đây là một ví dụ từ một số mã Tôi đã làm việc về nơi hướng dẫn nop nơi đặt vào mã byte (như xem bởi Bytecode Visualizer cho Eclipse)

Mã gốc

public abstract class Wrapper<T extends Wrapper<T,E>,E> 
    implements Supplier<Optional<E>>, Consumer<E> 
{ 
    /** The wrapped object. */ 
    protected Optional<E> inner; 

    /* 
    * (non-Javadoc) 
    * @see java.lang.Object#equals(java.lang.Object) 
    */ 
    /** 
    * A basic equals method that will compare the wrapped object to 
    * whatever you throw at it, whether it is wrapped or not. 
    */ 
    @Override 
    public boolean equals(final Object that) 
    { 
    return this==that 
     ||LambdaUtils.castAndMap(that,Wrapper.class,afterCast 
      -> inner.equals(afterCast.inner)) 
     .orElseGet(() 
      -> LambdaUtils.castAndMap(that,Optional.class,afterCast 
       -> inner.equals(afterCast)) 
      .orElseGet(() 
       -> Optional.ofNullable(that).map(thatobj 
        -> that.equals(inner.get())) 
       .orElseGet(() 
        -> false))); 
    } 
} 

Mã byte đã dịch cho phương thức equals (Object)

public boolean equals(java.lang.Object arg0) { 
    /* L27 */ 
    0 aload_0;    /* this */ 
    1 aload_1;    /* that */ 
    2 if_acmpeq 36; 
    /* L28 */ 
    5 aload_1;    /* that */ 
    6 ldc 1; 
    8 aload_0;    /* this */ 
    9 invokedynamic 29;  /* java.util.function.Function apply(ext.cat.wcutils.collections.Wrapper arg0) */ 
    12 nop; 
    13 nop; 
    14 invokestatic 30;  /* java.util.Optional ext.cat.wcutils.util.LambdaUtils.castAndMap(java.lang.Object arg0, java.lang.Class arg1, java.util.function.Function arg2) */ 
    /* L30 */ 
    17 aload_0;    /* this */ 
    18 aload_1;    /* that */ 
    19 invokedynamic 39;  /* java.util.function.Supplier get(ext.cat.wcutils.collections.Wrapper arg0, java.lang.Object arg1) */ 
    22 nop; 
    23 nop; 
    24 invokevirtual 40;  /* java.lang.Object orElseGet(java.util.function.Supplier arg0) */ 
    27 checkcast 46;   /* java.lang.Boolean */ 
    30 invokevirtual 48;  /* boolean booleanValue() */ 
    /* L37 */ 
    33 ifne 5; 
    /* L27 */ 
    36 iconst_0; 
    37 ireturn; 
    38 iconst_1; 
    39 ireturn; 
} 

Tôi không chắc chắn tại sao chúng được chèn vào. Tôi chỉ hy vọng họ không ảnh hưởng xấu đến hiệu suất.

+3

Không có 'nop', nó chỉ là một lỗi trong Trình hiển thị Bytecode mà bạn đã sử dụng. Lệnh 'invokedynamic' bao gồm năm byte, hai byte cuối cùng bằng không cho mỗi đặc tả. Rõ ràng, Trình hiển thị Bytecode không biết điều đó và giả định lệnh 'invokedynamic' chỉ có ba byte và giải thích sai hai byte số không dưới dạng các lệnh' nop'. Xem [InvM Spec invokedynamic] (https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokedynamic). – Holger

+0

Tôi đoán điều đó có ý nghĩa. Tôi đang chờ đợi một bản cập nhật cho Bytecode Visualizer cho Eclipse Neon. Có lẽ chúng ta nên nói với nhà phát triển. – HesNotTheStig

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