2016-01-16 14 views
10

Tôi nhận thấy một điều rất lạ sau khi thay đổi trường cuối cùng thông qua Reflection, phương thức trả về trường đó là tất cả thời gian cho giá trị cũ. Tôi cho rằng điều này có thể là do trình biên dịch JIT.Thay đổi giá trị cuối cùng được biên soạn bởi JIT

Đây là chương trình mẫu:

public class Main 
{ 
private static final Main m = new Main(); 
public static Main getM() 
{ 
    return m; 
} 

public static void main(String args[]) throws Exception 
{ 
    Main m = getM(); 
    int x = 0; 
    for(int i = 0;i<10000000;i++) 
    { 
     if(getM().equals(m)) 
      x ++; 
    } 
    Field f = Main.class.getDeclaredField("m"); 
    f.setAccessible(true); 
    removeFinal(f); 
    Main main1 = new Main(); 
    f.set(null, main1); 
    Main main2 = (Main) f.get(null); 
    Main main3 = getM(); 
    System.out.println(main1.toString()); 
    System.out.println(main2.toString()); 
    System.out.println(main3.toString()); 
} 

private static void removeFinal(Field field) throws NoSuchFieldException, IllegalAccessException 
{ 
    Field modifiersField = Field.class.getDeclaredField("modifiers"); 
    modifiersField.setAccessible(true); 
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); 
} 
} 

Kết quả là:

[email protected] 
[email protected] 
[email protected] 

tôi tự hỏi, làm thế nào tôi có thể làm getM() return cập nhật giá trị?

+3

Từ khóa 'final' cho phép trình biên dịch nội tuyến. Tại sao bạn cần phải làm điều này? –

+0

Có cách nào để buộc JIT biên dịch lại phương pháp này không? – user3009344

+1

Trình biên dịch javac, không phải là JIT. –

Trả lời

11

Tôi tự hỏi, làm thế nào tôi có thể làm cho getM() trả về giá trị cập nhật?

Với trận chung kết, bạn không thể. Trả lại giá trị "cũ" là hành vi hợp pháp, như JLS 17.5.3:

Thậm chí sau đó, có một số biến chứng. Nếu trường cuối cùng là được khởi tạo thành biểu thức không đổi (§15.28) trong trường khai báo, thay đổi trường cuối cùng có thể không được quan sát, vì sử dụng trường cuối cùng được thay thế tại thời gian biên dịch với giá trị của hằng số biểu hiện.

Một vấn đề khác là đặc điểm kỹ thuật cho phép tích cực tối ưu hóa các trường cuối cùng. Trong một chủ đề, được phép sắp xếp lại lần đọc của trường cuối cùng với những sửa đổi của trường cuối cùng không diễn ra trong hàm tạo.

Xem ví dụ hướng dẫn được bao gồm trong chương đó.

Nỗ lực khắc phục quy định này sẽ phải bao gồm gây rối với trình tối ưu hóa xuống ngăn xếp và dễ vỡ nhất. Nếu bạn đang chọn sửa đổi các trường, sau đó, theo định nghĩa, các trường đó không nên là cuối cùng. Nếu bạn muốn điều này vì lý do hiệu suất (đúng không?), Thì JSR 292 cung cấp cơ chế để làm các công trình "almost final".

+0

Khi có điều gì đó trong ứng dụng của tôi bị hỏng, có nhiều cách để khắc phục tạm thời/ẩn sự cố mà không cần khởi động lại ứng dụng, bằng cách tải bình nhỏ mới bằng truy cập vào các phương thức tĩnh. Đôi khi tôi cần phải thay đổi các lĩnh vực cuối cùng để sửa chữa một cái gì đó. Trong khi bình thường phản ánh hoạt động tốt trong trường hợp như vậy, đôi khi nó không vì vấn đề trong câu hỏi. Vì vậy, tôi đoán không có cách nào để vượt qua điều đó. – user3009344

1

Nếu bạn thực sự muốn thay đổi giá trị đó, Bạn có thể bọc lớp đó và ghi đè lên getter.

Có thể bạn đã nghe nội dung nào đó về mẫu "Ủy quyền"/"Proxy".

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