Việc tạo các tệp lớp Java có xác định không?


94

Khi sử dụng cùng một JDK (tức là cùng một javactệp thực thi), các tệp lớp được tạo luôn giống hệt nhau? Có thể có sự khác biệt tùy thuộc vào hệ điều hành hoặc phần cứng ? Ngoại trừ phiên bản JDK, có thể có bất kỳ yếu tố nào khác dẫn đến sự khác biệt không? Có bất kỳ tùy chọn trình biên dịch nào để tránh sự khác biệt không? Sự khác biệt chỉ có thể là trên lý thuyết hay Oracle javacthực sự tạo ra các tệp lớp khác nhau cho các tùy chọn đầu vào và trình biên dịch giống nhau?

Cập nhật 1 Tôi quan tâm đến việc tạo , tức là đầu ra của trình biên dịch, chứ không phải liệu một tệp lớp có thể chạy trên các nền tảng khác nhau hay không.

Cập nhật 2 Bởi 'Cùng một JDK', tôi cũng có nghĩa là cùng một javactệp thực thi.

Cập nhật 3 Sự khác biệt giữa sự khác biệt lý thuyết và sự khác biệt thực tế trong các trình biên dịch của Oracle.

[CHỈNH SỬA, thêm câu hỏi được diễn giải]
"Đâu là trường hợp mà cùng một tệp thực thi javac, khi chạy trên một nền tảng khác, sẽ tạo ra mã bytecode khác nhau?"


5
@Gamb CORA không có nghĩa là mã byte sẽ hoàn toàn giống nhau nếu được biên dịch trên các nền tảng khác nhau; tất cả điều đó có nghĩa là mã byte được tạo sẽ thực hiện chính xác những điều tương tự.
dasblinkenlight 20/02

10
Bạn quan tâm làm gì? Điều này có mùi giống như một vấn đề XY .
Joachim Sauer

4
@JoachimSauer Hãy xem xét nếu phiên bản của bạn kiểm soát các tệp nhị phân của mình - bạn có thể chỉ muốn phát hiện các thay đổi khi mã nguồn đã thay đổi, nhưng bạn sẽ biết đây không phải là một ý tưởng hợp lý nếu JDK có thể tự ý thay đổi các tệp nhị phân đầu ra.
RB.

7
@RB .: trình biên dịch được phép tạo ra bất kỳ mã byte phù hợp nào đại diện cho mã đã biên dịch. Trên thực tế, một số bản cập nhật trình biên dịch sửa lỗi tạo ra mã hơi khác (thường có cùng hành vi thời gian chạy). Nói cách khác: nếu bạn muốn phát hiện các thay đổi nguồn, hãy kiểm tra các thay đổi nguồn.
Joachim Sauer

3
@dasblinkenlight: bạn đang giả định rằng câu trả lời mà họ tuyên bố là thực sự đúng và cập nhật (nghi ngờ, vì câu hỏi là từ năm 2003).
Joachim Sauer

Câu trả lời:


68

Hãy đặt nó theo cách này:

Tôi có thể dễ dàng tạo ra một trình biên dịch Java hoàn toàn phù hợp mà không bao giờ tạo ra cùng một .classtệp hai lần, cho cùng một .javatệp.

Tôi có thể làm điều này bằng cách điều chỉnh tất cả các loại cấu trúc bytecode hoặc chỉ cần thêm các thuộc tính thừa vào phương thức của tôi (được phép).

Do đặc điểm kỹ thuật không yêu cầu trình biên dịch tạo ra các tệp lớp giống nhau từng byte, tôi sẽ tránh phụ thuộc vào kết quả như vậy.

Tuy nhiên , một vài lần tôi đã kiểm tra, việc biên dịch cùng một tệp nguồn với cùng một trình biên dịch với cùng một công tắc (và cùng một thư viện!) Đã dẫn đến các .classtệp giống nhau .

Cập nhật: Gần đây tôi đã tình cờ đọc được bài đăng trên blog thú vị này về việc triển khai switchtrên Stringtrong Java 7 . Trong bài đăng blog này, có một số phần liên quan, mà tôi sẽ trích dẫn ở đây (phần nhấn mạnh của tôi):

Để làm cho đầu ra của trình biên dịch có thể dự đoán được và có thể lặp lại, các bản đồ và tập hợp được sử dụng trong các cấu trúc dữ liệu này là LinkedHashMaps và LinkedHashSets thay vì chỉ HashMapsHashSets. Về mặt chức năng đúng đắn của mã được tạo ra trong quá trình biên dịch nhất định, sử dụng HashMapHashSetsẽ ổn ; thứ tự lặp lại không quan trọng. Tuy nhiên, chúng tôi thấy có lợi khi javacđầu ra của không thay đổi dựa trên chi tiết triển khai của các lớp hệ thống .

Điều này minh họa khá rõ ràng vấn đề: Trình biên dịch không bắt buộc phải hoạt động theo cách xác định, miễn là nó phù hợp với thông số kỹ thuật. Tuy nhiên, các nhà phát triển trình biên dịch nhận ra rằng nói chung là một ý tưởng hay để thử (có thể là nó không quá đắt).


@GaborSch nó bị thiếu cái gì? "Những trường hợp nào mà cùng một tệp thực thi javac, khi chạy trên một nền tảng khác, sẽ tạo ra mã bytecode khác nhau?" về cơ bản tùy thuộc vào ý thích của nhóm đã sản xuất trình biên dịch
emory

3
Đối với tôi, đây sẽ là lý do đủ để không phụ thuộc vào nó: một JDK được cập nhật có thể phá vỡ hệ thống xây dựng / lưu trữ của tôi nếu tôi phụ thuộc vào thực tế là trình biên dịch luôn tạo ra cùng một mã.
Joachim Sauer

3
@GaborSch: bạn đã có một ví dụ hoàn toàn tốt về tình huống như vậy, vì vậy một số quan điểm bổ sung về vấn đề đã được thực hiện. Không có ý nghĩa gì trong việc sao chép công việc của bạn.
Joachim Sauer

1
@GaborSch Vấn đề cơ bản là chúng tôi muốn triển khai "cập nhật trực tuyến" hiệu quả cho ứng dụng của mình mà người dùng sẽ chỉ tìm nạp các JAR đã sửa đổi từ trang web. Tôi có thể tạo các JAR giống hệt nhau có các tệp lớp giống hệt nhau làm đầu vào. Nhưng câu hỏi đặt ra là liệu các tệp lớp luôn giống nhau khi được biên dịch từ các tệp nguồn giống nhau. Toàn bộ khái niệm của chúng tôi đứng và thất bại với thực tế này.
mstrap

2
@mstrap: vậy nó là một vấn đề XY. Chà, bạn có thể xem xét các bản cập nhật khác nhau của các lọ (vì vậy, ngay cả sự khác biệt một byte cũng không khiến toàn bộ lọ được tải xuống lại) và dù sao thì bạn cũng nên cung cấp số phiên bản rõ ràng cho các bản phát hành của mình, vì vậy, toàn bộ điểm đó là tranh luận, theo ý kiến ​​của tôi .
Joachim Sauer

38

Các trình biên dịch không có nghĩa vụ phải tạo ra cùng một mã byte trên mỗi nền tảng. Bạn nên tham khảo javactiện ích của các hãng khác nhau để có câu trả lời cụ thể.


Tôi sẽ đưa ra một ví dụ thực tế cho điều này với thứ tự tệp.

Giả sử rằng chúng ta có 2 tệp jar: my1.jarMy2.jar. Chúng được đặt cạnh nhau trong libthư mục. Trình biên dịch lần đọc chúng theo thứ tự chữ cái (vì đây là lib), nhưng thứ tự là my1.jar, My2.jarkhi hệ thống tập tin là trường hợp nhạy cảm, và My2.jar, my1.jarnếu nó là trường hợp nhạy cảm.

my1.jarmột lớp A.classvới một phương thức

public class A {
     public static void a(String s) {}
}

My2.jarcùng A.class, nhưng với chữ ký phương thức khác nhau (chấp nhận Object):

public class A {
     public static void a(Object o) {}
}

Rõ ràng rằng nếu bạn có một cuộc gọi

String s = "x"; 
A.a(s); 

nó sẽ biên dịch một cuộc gọi phương thức với các chữ ký khác nhau trong các trường hợp khác nhau. Vì vậy, tùy thuộc vào độ nhạy chữ hoa chữ thường của hệ thống tệp, kết quả là bạn sẽ nhận được các lớp khác nhau.


1
+1 Có vô số khác biệt giữa trình biên dịch Eclipse và javac, ví dụ như cách tạo các hàm tạo tổng hợp .
Paul Bellora

2
@GaborSch Tôi quan tâm đến việc mã byte có giống hệt nhau cho cùng một JDK hay không, tức là cùng một javac. Tôi sẽ nói rõ hơn.
mstrap

2
@mstrap Tôi đã hiểu câu hỏi của bạn, nhưng câu trả lời vẫn vậy: tùy thuộc vào nhà cung cấp. Các javaclà không giống nhau, bởi vì bạn có mã nhị phân khác nhau trên mỗi nền tảng (ví dụ Win7, Linux, Solaris, Mac). Đối với một nhà cung cấp, không có ý nghĩa gì khi có các cách triển khai khác nhau, nhưng bất kỳ vấn đề cụ thể của nền tảng nào cũng có thể ảnh hưởng đến kết quả (ví dụ: đặt hàng flie trong một thư mục (suy nghĩ về libthư mục của bạn ), endianness, v.v.).
gaborsch

1
Thông thường, hầu hết javacđược triển khai bằng Java (và javacchỉ là một launcher gốc đơn giản), vì vậy hầu hết các khác biệt về nền tảng sẽ không có tác động.
Joachim Sauer

2
@mstrap - quan điểm mà anh ấy đang đưa ra là không có yêu cầu đối với bất kỳ nhà cung cấp nào phải làm cho trình biên dịch của họ tạo ra chính xác cùng một mã bytecode trên các nền tảng, chỉ có điều là mã bytecode tạo ra sẽ tạo ra cùng một kết quả. Do không có tiêu chuẩn / thông số kỹ thuật / yêu cầu, câu trả lời cho câu hỏi của bạn là "Nó phụ thuộc vào nhà cung cấp, trình biên dịch và nền tảng cụ thể".
Brian Roach,

6

Câu trả lời ngắn - KHÔNG


Câu trả lời dài

Chúng bytecodekhông cần giống nhau cho các nền tảng khác nhau. Đó là JRE (Java Runtime Environment) biết cách thực thi bytecode một cách chính xác.

Nếu bạn xem qua thông số kỹ thuật của máy ảo Java, bạn sẽ biết rằng điều này không cần phải đúng khi mã bytecode giống nhau đối với các nền tảng khác nhau.

Xem qua định dạng tệp lớp , nó hiển thị cấu trúc của tệp lớp như

ClassFile {
    u4 magic;
    u2 minor_version;
    u2 major_version;
    u2 constant_pool_count;
    cp_info constant_pool[constant_pool_count-1];
    u2 access_flags;
    u2 this_class;
    u2 super_class;
    u2 interfaces_count;
    u2 interfaces[interfaces_count];
    u2 fields_count;
    field_info fields[fields_count];
    u2 methods_count;
    method_info methods[methods_count];
    u2 attributes_count;
    attribute_info attributes[attributes_count];
}

Kiểm tra về phiên bản nhỏ và chính

small_version, major_version

Các giá trị của mục small_version và major_version là số phiên bản chính và phụ của tệp lớp này. Nhìn chung, số phiên bản chính và phụ xác định phiên bản của định dạng tệp lớp. Nếu một tệp lớp có số phiên bản chính là M và số phiên bản phụ là m, chúng tôi ký hiệu phiên bản của định dạng tệp lớp là Mm Do đó, các phiên bản định dạng tệp lớp có thể được sắp xếp theo từ điển, ví dụ: 1,5 <2,0 <2,1. Việc triển khai máy ảo Java có thể hỗ trợ định dạng tệp lớp của phiên bản v nếu và chỉ khi v nằm trong một số phạm vi tiếp giáp Mi.0 v Mj.m. Chỉ Sun mới có thể chỉ định phạm vi phiên bản mà triển khai máy ảo Java phù hợp với một mức phát hành nhất định của nền tảng Java có thể hỗ trợ.1

Đọc thêm qua chú thích

1 Việc triển khai máy ảo Java của bản phát hành JDK 1.0.2 của Sun hỗ trợ định dạng tệp lớp từ phiên bản 45.0 đến 45.3. Sun's JDK phát hành 1.1.X có thể hỗ trợ các định dạng tệp lớp của các phiên bản trong phạm vi từ 45.0 đến 45.65535 bao gồm cả. Việc triển khai phiên bản 1.2 của nền tảng Java 2 có thể hỗ trợ các định dạng tệp lớp của các phiên bản trong phạm vi từ 45.0 đến 46.0.

Vì vậy, điều tra tất cả những điều này cho thấy rằng các tệp lớp được tạo trên các nền tảng khác nhau không cần phải giống hệt nhau.


Bạn có thể cung cấp cho một liên kết chi tiết hơn xin vui lòng?
mstrap

Tôi nghĩ theo 'nền tảng' họ đang đề cập đến nền tảng Java, không phải hệ điều hành. Tất nhiên, khi hướng dẫn javac 1.7 tạo các tệp lớp tương thích 1.6 sẽ có sự khác biệt.
mstrap

@mtk +1 để hiển thị số lượng thuộc tính được tạo cho một lớp đơn lẻ trong quá trình biên dịch.
gaborsch

3

Thứ nhất, không có gì đảm bảo như vậy trong thông số kỹ thuật. Một trình biên dịch phù hợp có thể đóng dấu thời gian biên dịch vào tệp lớp được tạo như một thuộc tính bổ sung (tùy chỉnh) và tệp lớp sẽ vẫn đúng. Tuy nhiên, nó sẽ tạo ra một tệp khác nhau ở cấp độ byte trên mỗi bản dựng đơn lẻ và rất hiếm khi xảy ra.

Thứ hai, ngay cả khi không có những thủ thuật khó chịu như vậy, không có lý do gì để mong đợi một trình biên dịch làm chính xác cùng một việc hai lần liên tiếp trừ khi cả cấu hình và đầu vào của nó giống hệt nhau trong hai trường hợp. Spec không mô tả tên file nguồn là một trong những thuộc tính tiêu chuẩn, và thêm dòng trống để các tập tin nguồn cũng có thể thay đổi bảng số dòng.

Thứ ba, tôi chưa bao giờ gặp phải bất kỳ sự khác biệt nào trong việc xây dựng do nền tảng máy chủ (ngoài điều đó được cho là do sự khác biệt về những gì trên classpath). Mã sẽ thay đổi dựa trên nền tảng (tức là các thư viện mã gốc) không phải là một phần của tệp lớp và việc tạo mã gốc thực sự từ mã bytecode sẽ xảy ra sau khi lớp được tải.

Thứ tư (và quan trọng nhất) nó ám mùi quy trình tồi tệ (giống như mùi mã, nhưng đối với cách bạn hành động trên mã) để muốn biết điều này. Phiên bản nguồn nếu có thể, không phải phiên bản và nếu bạn cần phiên bản phiên bản, phiên bản ở cấp toàn bộ thành phần chứ không phải trên các tệp lớp riêng lẻ. Để được ưu tiên, hãy sử dụng máy chủ CI (chẳng hạn như Jenkins) để quản lý quá trình chuyển mã nguồn thành mã chạy được.


2

Tôi tin rằng, nếu bạn sử dụng cùng một JDK, mã byte được tạo sẽ luôn giống nhau, không liên quan đến harware và hệ điều hành được sử dụng. Việc sản xuất mã byte được thực hiện bởi trình biên dịch java, sử dụng thuật toán xác định để "chuyển đổi" mã nguồn thành mã byte. Vì vậy, đầu ra sẽ luôn giống nhau. Trong những điều kiện này, chỉ một bản cập nhật trên mã nguồn sẽ ảnh hưởng đến đầu ra.


3
Bạn có tài liệu tham khảo cho điều này mặc dù? Như tôi đã nói trong phần nhận xét câu hỏi, đây chắc chắn không phải là trường hợp của C # , vì vậy rất muốn xem một tài liệu tham khảo cho biết đó là trường hợp của Java. Tôi đặc biệt nghĩ rằng một trình biên dịch đa luồng có thể gán các tên định danh khác nhau trên các lần chạy khác nhau.
RB.

1
Đây là câu trả lời cho câu hỏi của tôi và những gì tôi mong đợi, tuy nhiên tôi đồng ý với RB rằng một tài liệu tham khảo cho điều đó sẽ rất quan trọng.
mstrap

Tôi cũng tin như vậy. Tôi không nghĩ rằng bạn sẽ tìm thấy một tài liệu tham khảo chắc chắn. Nếu nó quan trọng đối với bạn thì bạn có thể thực hiện một nghiên cứu. Thu thập một loạt những cái hàng đầu và thử chúng trên các nền tảng khác nhau để biên dịch một số mã nguồn mở. So sánh các tệp byte. Công bố kết quả. Hãy chắc chắn để đặt một liên kết ở đây.
emory

1

Nhìn chung, tôi phải nói rằng không có gì đảm bảo rằng cùng một nguồn sẽ tạo ra cùng một mã bytecode khi được biên dịch bởi cùng một trình biên dịch nhưng trên một nền tảng khác.

Tôi sẽ xem xét các tình huống liên quan đến các ngôn ngữ khác nhau (trang mã), ví dụ như Windows có hỗ trợ tiếng Nhật. Hãy suy nghĩ các ký tự nhiều byte; trừ khi trình biên dịch luôn giả định rằng nó cần hỗ trợ tất cả các ngôn ngữ mà nó có thể tối ưu hóa cho ASCII 8-bit.

Có một phần về khả năng tương thích nhị phân trong Đặc tả ngôn ngữ Java .

Trong khuôn khổ Khả năng tương thích nhị phân từ bản phát hành đến bản phát hành trong SOM (Forman, Conner, Danforth và Raper, Proceedings of OOPSLA '95), các mã nhị phân của ngôn ngữ lập trình Java tương thích nhị phân với tất cả các phép biến đổi có liên quan mà các tác giả xác định (với một số lưu ý đối với việc bổ sung các biến cá thể). Sử dụng lược đồ của họ, đây là danh sách một số thay đổi tương thích nhị phân quan trọng mà ngôn ngữ lập trình Java hỗ trợ:

• Thực hiện lại các phương thức, hàm tạo và trình khởi tạo hiện có để cải thiện hiệu suất.

• Thay đổi các phương thức hoặc hàm tạo để trả về giá trị trên các đầu vào mà trước đó chúng đã ném ra các ngoại lệ thường không xảy ra hoặc không thành công bằng cách đi vào vòng lặp vô hạn hoặc gây ra bế tắc.

• Thêm các trường, phương thức hoặc hàm tạo mới vào một lớp hoặc giao diện hiện có.

• Xóa các trường, phương thức hoặc hàm tạo riêng của một lớp.

• Khi toàn bộ gói được cập nhật, xóa các trường, phương thức hoặc phương thức truy cập mặc định (chỉ gói) của các lớp và giao diện trong gói.

• Sắp xếp lại thứ tự các trường, phương thức hoặc hàm tạo trong một khai báo kiểu hiện có.

• Di chuyển một phương thức lên trong phân cấp lớp.

• Sắp xếp lại thứ tự danh sách các bề mặt trực tiếp của một lớp hoặc giao diện.

• Chèn lớp hoặc kiểu giao diện mới trong hệ thống phân cấp kiểu.

Chương này quy định các tiêu chuẩn tối thiểu cho khả năng tương thích nhị phân được đảm bảo bởi tất cả các triển khai. Ngôn ngữ lập trình Java đảm bảo tính tương thích khi các tệp nhị phân của các lớp và giao diện được trộn lẫn mà không được biết là từ các nguồn tương thích, nhưng các nguồn của chúng đã được sửa đổi theo các cách tương thích được mô tả ở đây. Lưu ý rằng chúng tôi đang thảo luận về khả năng tương thích giữa các bản phát hành của một ứng dụng. Phần thảo luận về khả năng tương thích giữa các bản phát hành của nền tảng Java SE nằm ngoài phạm vi của chương này.


Bài viết đó thảo luận về những gì có thể xảy ra khi chúng tôi thay đổi phiên bản Java. Câu hỏi của OP là điều gì có thể xảy ra nếu chúng tôi thay đổi nền tảng trong cùng một phiên bản Java. Nếu không thì đó là một bắt tốt.
gaborsch

1
Nó gần như tôi có thể tìm thấy. Có một lỗ hổng kỳ lạ giữa thông số của ngôn ngữ và thông số của JVM. Cho đến nay, tôi phải trả lời OP là 'không có gì đảm bảo rằng cùng một trình biên dịch java sẽ tạo ra cùng một mã bytecode khi chạy trên một nền tảng khác.'
Kelly S. French

1

Java allows you write/compile code on one platform and run on different platform. AFAIK ; điều này sẽ chỉ có thể thực hiện được khi tệp lớp được tạo trên nền tảng khác giống nhau hoặc giống nhau về mặt kỹ thuật tức là giống hệt nhau.

Biên tập

Ý tôi là về mặt kỹ thuật cùng một nhận xét là như vậy. Chúng không cần phải hoàn toàn giống nhau nếu bạn so sánh từng byte.

Vì vậy, theo đặc điểm kỹ thuật, tệp .class của một lớp trên các nền tảng khác nhau không cần phải khớp từng byte.


Câu hỏi của OP liệu các tệp lớp có giống nhau hay "giống nhau về mặt kỹ thuật".
bdesham

Tôi quan tâm liệu chúng có giống nhau không .
mstrap

và trả lời là có. ý tôi là chúng có thể không giống nhau nếu bạn so sánh từng byte, đó là lý do tại sao tôi sử dụng từ giống nhau về mặt kỹ thuật.
rai.skumar

@bdesham anh ấy muốn biết liệu chúng có giống nhau không. không chắc những gì bạn hiểu bởi "về mặt kỹ thuật giống nhau" ... đó là lý do cho downvote?
rai.skumar

@ rai.skumar Câu trả lời của bạn về cơ bản là "Hai trình biên dịch sẽ luôn tạo ra kết quả hoạt động giống nhau." Tất nhiên điều này là đúng; đó là toàn bộ động lực của nền tảng Java. OP muốn biết liệu mã được phát ra có phải là byte đối với byte giống hệt nhau hay không mà bạn không nêu trong câu trả lời của mình.
bdesham

1

Đối với câu hỏi:

"Những trường hợp nào mà cùng một tệp thực thi javac, khi chạy trên một nền tảng khác, sẽ tạo ra mã bytecode khác nhau?"

Các Cross-Compilation ví dụ cho thấy cách chúng ta có thể sử dụng tùy chọn Javac: phiên bản -target

Cờ này tạo các tệp lớp tương thích với phiên bản Java mà chúng tôi chỉ định trong khi gọi lệnh này. Do đó, các tệp lớp sẽ khác nhau tùy thuộc vào các thuộc tính mà chúng tôi cung cấp trong quá trình so sánh bằng cách sử dụng tùy chọn này.


0

Có thể nhất, câu trả lời là "có", nhưng để có câu trả lời chính xác, người ta cần phải tìm kiếm một số khóa hoặc tạo hướng dẫn trong quá trình biên dịch.

Tôi không thể nhớ tình huống xảy ra điều này. Ví dụ: để có ID cho mục đích tuần tự hóa, nó được mã hóa cứng, tức là do lập trình viên hoặc IDE tạo ra.

PS Ngoài ra JNI có thể quan trọng.

PPS Tôi thấy rằng javacbản thân nó được viết bằng java. Điều này có nghĩa là nó giống hệt nhau trên các nền tảng khác nhau. Do đó, nó sẽ không tạo mã khác mà không có lý do. Vì vậy, nó có thể làm điều này chỉ với các cuộc gọi bản địa.


Lưu ý rằng Java không bảo vệ bạn khỏi mọi sự khác biệt về nền tảng. Thứ tự của các tệp được trả về khi liệt kê nội dung thư mục không được xác định và điều này thể có một số tác động đến trình biên dịch.
Joachim Sauer

0

Có hai câu hỏi.

Can there be a difference depending on the operating system or hardware? 

Đây là một câu hỏi lý thuyết, và câu trả lời là rõ ràng, có, có thể có. Như những người khác đã nói, đặc tả không yêu cầu trình biên dịch tạo ra các tệp lớp giống nhau từng byte.

Ngay cả khi mọi trình biên dịch hiện đang tồn tại đều tạo ra cùng một mã byte trong mọi trường hợp (phần cứng khác nhau, v.v.), câu trả lời vào ngày mai có thể khác. Nếu bạn không bao giờ có kế hoạch cập nhật javac hoặc hệ điều hành của mình, bạn có thể kiểm tra hành vi của phiên bản đó trong các trường hợp cụ thể của mình, nhưng kết quả có thể khác nếu bạn chuyển từ, chẳng hạn như Java 7 Update 11 sang Java 7 Update 15.

What are the circumstances where the same javac executable, when run on a different platform, will produce different bytecode?

Không thể biết được.

Tôi không biết quản lý cấu hình có phải là lý do bạn đặt câu hỏi hay không, nhưng đó là lý do dễ hiểu để bạn quan tâm. So sánh mã byte là một kiểm soát CNTT hợp pháp, nhưng chỉ để xác định xem tệp lớp có thay đổi hay không, chứ không phải xác định xem tệp nguồn có thay đổi hay không.


0

Tôi sẽ đặt nó theo cách khác.

Đầu tiên, tôi nghĩ câu hỏi không phải là về tính xác định:

Tất nhiên nó mang tính xác định: tính ngẫu nhiên khó đạt được trong khoa học máy tính, và không có lý do gì mà một trình biên dịch lại giới thiệu nó ở đây vì bất kỳ lý do gì.

Thứ hai, nếu bạn định dạng lại nó bằng cách "các tệp bytecode giống nhau như thế nào cho cùng một tệp mã nguồn?", Thì Không , bạn không thể dựa vào thực tế là chúng sẽ giống nhau .

Một cách tốt để đảm bảo điều này là để lại .class (hoặc .pyc trong trường hợp của tôi) trong giai đoạn git của bạn. Bạn sẽ nhận ra rằng giữa các máy tính khác nhau trong nhóm của mình, git thông báo thay đổi giữa các tệp .pyc, khi không có thay đổi nào được đưa đến tệp .py (và .pyc vẫn được biên dịch lại).

Ít nhất đó là những gì tôi quan sát được. Vì vậy, hãy đặt * .pyc và * .class trong .gitignore của bạn!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.