2017-04-22 21 views
22

Tôi đã dành nhiều thời gian điều tra một số tính năng mới của Java 9, nhưng tôi không tìm thấy bất kỳ ví dụ hữu ích và thực tế nào.Cách đúng để sử dụng VarHandle trong Java 9?

Hãy xem xét đoạn mã tiếp theo mà tạo ra một VarHandle:

class Counter { 
    int i; 
} 

class VarHandleInAction { 
    static final VarHandle VH_COUNTER_FIELD_I; 

    static { 
     try { 
      VH_COUNTER_FIELD_I = MethodHandles.lookup(). 
       in(Counter.class). 
       findVarHandle(Counter.class, "i", int.class); 
     } catch (Exception e) { 
      // ... 
     } 
    } 
} 

Nhưng những gì tiếp theo? Ý tôi là, làm cách nào để sử dụng Bộ xử lý biến này ? Bạn có thể cung cấp bất kỳ ví dụ thực tế nào không?

+9

xử lý Var (hoặc phương pháp xử lý) khá API cấp thấp cho các thao tác phương thức và hoạt động bộ nhớ. Hầu hết mọi người sẽ không bao giờ cần phải sử dụng các API đó. –

Trả lời

24

Nó được sử dụng ví dụ trong AtomicReference, nơi mà trước đây trong Java 8, sun.misc.Unsafe đã được sử dụng:

public final void lazySet(V newValue) { 
    unsafe.putOrderedObject(this, valueOffset, newValue); 
} 

public final boolean compareAndSet(V expect, V update) { 
    return unsafe.compareAndSwapObject(this, valueOffset, expect, update); 
} 

đây con trỏ this được sử dụng cùng với một trường offset để truy cập lĩnh vực này. Nhưng điều này là không an toàn, vì bù trừ trường này có thể là bất kỳ long và bạn thực sự có thể truy cập vào một thứ hoàn toàn khác. Tuy nhiên, có những lợi ích hiệu năng khi thực hiện theo cách này (nó yêu cầu máy ảo sử dụng các chỉ dẫn CPU chuyên biệt) và do đó người khác đã sử dụng sun.misc.Unsafe mặc dù đó là một API nội bộ và không an toàn.

Một phần của mục đích cho VarHandles là thay thế các hoạt động trong sun.misc.Unsafe bằng cách tương đương an toàn. Đó là quy định tại the JEP:

Xác định một phương tiện tiêu chuẩn để gọi tương đương của nhiều hoạt động java.util.concurrent.atomic và sun.misc.Unsafe ...

Mục tiêu :

sau đây mục tiêu được yêu cầu:

  • An toàn. Không thể đặt Máy ảo Java trong trạng thái bộ nhớ bị hỏng. Ví dụ, một trường của một đối tượng chỉ có thể được cập nhật với các cá thể có thể chuyển sang kiểu trường hoặc phần tử mảng chỉ có thể được truy cập trong một mảng nếu chỉ mục mảng nằm trong giới hạn mảng.

  • Tính toàn vẹn. Truy cập vào một trường của một đối tượng theo cùng các quy tắc truy cập như với các mã byte getfield và putfield ngoài ràng buộc rằng một trường cuối cùng của một đối tượng không thể được cập nhật. (Lưu ý: các quy tắc an toàn và toàn vẹn như vậy cũng áp dụng cho MethodHandles cấp quyền truy cập đọc hoặc ghi vào một trường.)

  • Hiệu suất. Các đặc tính hiệu suất phải giống hoặc tương tự như các hoạt động sun.misc.Unsafe tương đương (cụ thể, mã trình tạo được tạo ra phải gần như giống hệt nhau một số kiểm tra an toàn nhất định không thể gấp lại được).

  • Tính khả dụng. API phải tốt hơn API sun.misc.Unsafe.

Vì vậy, trong Java 9 những phương pháp giống như thế này:

public final void lazySet(V newValue) { 
    VALUE.setRelease(this, newValue); 
} 

public final boolean compareAndSet(V expectedValue, V newValue) { 
    return VALUE.compareAndSet(this, expectedValue, newValue); 
} 

đâu VALUE là một VarHandle định nghĩa như thế này:

private static final VarHandle VALUE; 
static { 
    try { 
     MethodHandles.Lookup l = MethodHandles.lookup(); 
     VALUE = l.findVarHandle(AtomicReference.class, "value", Object.class); 
    } catch (ReflectiveOperationException e) { 
     throw new Error(e); 
    } 
} 
Các vấn đề liên quan