Java là ngôn ngữ lập trình được biên dịch hay giải thích?


169

Trong quá khứ tôi đã sử dụng C ++ làm ngôn ngữ lập trình. Tôi biết rằng mã được viết bằng C ++ trải qua quá trình biên dịch cho đến khi nó trở thành mã đối tượng "mã máy".

Tôi muốn biết Java hoạt động như thế nào trong khía cạnh đó. Làm thế nào là người dùng viết mã Java được chạy bởi máy tính?


14
C ++ có thể được giải thích. Có một vài thông dịch viên C ngoài kia.
Tom Hawtin - tackline

Câu trả lời:


220

Việc triển khai Java thường sử dụng quy trình biên dịch hai bước. Mã nguồn Java được biên dịch xuống mã byte bởi trình biên dịch Java. Mã byte được thực thi bởi Máy ảo Java (JVM). Các JVM hiện đại sử dụng một kỹ thuật gọi là biên dịch Just-in-Time (JIT) để biên dịch mã byte theo các lệnh gốc được hiểu bởi CPU phần cứng khi đang chạy.

Một số triển khai của JVM có thể chọn giải thích mã byte thay vì JIT biên dịch nó thành mã máy và chạy trực tiếp. Mặc dù đây vẫn được coi là "trình thông dịch", nó khác hoàn toàn với các trình thông dịch đọc và thực thi mã nguồn mức cao (nghĩa là trong trường hợp này, mã nguồn Java không được giải thích trực tiếp, mã byte, đầu ra của trình biên dịch Java, là.)

Về mặt kỹ thuật có thể biên dịch Java xuống mã gốc trước thời hạn và chạy nhị phân kết quả. Cũng có thể diễn giải mã Java trực tiếp.

Để tóm tắt, tùy thuộc vào môi trường thực thi, mã byte có thể là:

  • được biên dịch trước thời hạn và được thực thi dưới dạng mã gốc (tương tự như hầu hết các trình biên dịch C ++)
  • biên dịch đúng lúc và thực hiện
  • giải thích
  • được thực thi trực tiếp bởi bộ xử lý được hỗ trợ (mã byte là tập lệnh gốc của một số CPU)

20
Trên thực tế, một số JVM của HotSpot bắt đầu bằng cách giải thích mã byte và chỉ biên dịch chúng thành mã gốc sau khi chúng tìm ra cái gì đáng để biên dịch và thu thập một số thống kê về cách mã đang được chạy; ví dụ để tìm ra con đường phổ biến nhất được thực hiện trong mỗi nhánh có điều kiện.
Stephen C

1
Do đó, thuật ngữ 'Hotspot' :) Nó thực hiện theo những gì đang chạy thường xuyên, để đạt được sự tối ưu hóa.
Trưa Tơ

4
Bạn có thể tắt trình thông dịch trong HotSpot bằng -Xcomp. Đáng để thử trên một ứng dụng để xem ý tưởng tồi là gì.
Tom Hawtin - tackline

1
Có một tuyên bố "Phiên bản hiện tại của Sun HotSpot JVM sử dụng một kỹ thuật gọi là biên dịch Just-in-time (JIT) để biên dịch mã byte theo các lệnh gốc được hiểu bởi CPU khi đang chạy." Tôi đã có ấn tượng rằng JVM là một trình thông dịch nhưng nó gợi ý rằng nó biên dịch thêm mã byte. Tôi bị bối rối. Ngoài ra nó được viết rằng nó làm điều đó một cách nhanh chóng trong thời gian chạy. Ai đó cũng có thể giải thích điều này?
Anand

vì java là ngôn ngữ được diễn giải nên nó sẽ ảnh hưởng đến hiệu suất hoặc bất kỳ thực thi ứng dụng java nào
NAND

93

nhập mô tả hình ảnh ở đây

Mã được viết bằng Java là:

  • Lần đầu tiên được biên dịch sang mã byte bởi một chương trình có tên là javac như được hiển thị trong phần bên trái của hình ảnh ở trên;
  • Sau đó, như được hiển thị trong phần bên phải của hình ảnh trên, một chương trình khác có tên java khởi động môi trường thời gian chạy Java và nó có thể biên dịch và / hoặc giải thích mã byte bằng cách sử dụng Trình biên dịch Java / Trình biên dịch JIT.

Khi nào java diễn giải mã byte và khi nào nó biên dịch nó? Mã ứng dụng ban đầu được hiểu, nhưng JVM theo dõi các chuỗi mã byte thường được thực thi và chuyển chúng thành mã máy để thực thi trực tiếp trên phần cứng. Đối với mã byte chỉ được thực thi một vài lần, điều này giúp tiết kiệm thời gian biên dịch và giảm độ trễ ban đầu; đối với mã byte được thực thi thường xuyên, quá trình biên dịch JIT được sử dụng để chạy ở tốc độ cao, sau giai đoạn giải thích chậm ban đầu. Ngoài ra, do một chương trình dành phần lớn thời gian để thực thi một thiểu số mã của nó, thời gian biên dịch giảm là rất đáng kể. Cuối cùng, trong quá trình giải thích mã ban đầu, số liệu thống kê thực hiện có thể được thu thập trước khi biên dịch, giúp thực hiện tối ưu hóa tốt hơn.


Có phải do mã byte được lưu trữ mà Java sử dụng rất nhiều bộ nhớ?
Pedro Gordo

3
@sedulam: 'Nhiều bộ nhớ' là một câu lệnh mờ. Quản lý bộ nhớ của Java khá đơn giản - Ba thế hệ là những gì JVM sử dụng để tạo và bảo trì các đối tượng của nó. Đây câu trả lời SO khác có thể hữu ích cho bạn.
displayName

Với giải thích ở trên, về mặt lý thuyết, mã được biên dịch C ++ sẽ luôn nhanh hơn mã java tương tự về mặt logic vì sẽ luôn có một phần của tệp. Class mà JIT quyết định không chuyển đổi thành mã máy. Nói cách khác, java không bao giờ có thể bắt được tốc độ thực hiện kim loại trần mà C ++ đã thể hiện. Đây có phải là giả định chính xác?
DevdattaK

@DevdattaK: Tôi không biết nhiều về C ++ nhưng tôi đoán là đối với các chương trình nhỏ hơn và chuyên biệt, Java có thể cho bạn kết quả nhanh hơn vì sẽ không lãng phí thời gian biên dịch các phần mã đó khi không có nhiều tốc độ.
displayName

1
@DevdattaK giả định của bạn được thảo luận trong trang wiki này en.m.wikipedia.org/wiki/Java_performance?wprov=sfla1 Tóm lại, điều đó không phải lúc nào cũng đúng.
Sundar Rajan

57

Các thuật ngữ "ngôn ngữ được giải thích" hoặc "ngôn ngữ được biên dịch" không có nghĩa, bởi vì bất kỳ ngôn ngữ lập trình nào cũng có thể được diễn giải và / hoặc biên dịch.

Đối với các triển khai Java hiện có, hầu hết liên quan đến một bước biên dịch thành mã byte , vì vậy chúng liên quan đến việc biên dịch. Thời gian chạy cũng có thể tải mã byte một cách linh hoạt, vì vậy luôn cần một số dạng trình thông dịch mã byte. Trình thông dịch đó có thể hoặc không thể lần lượt sử dụng biên dịch thành mã riêng trong nội bộ.

Ngày nay, việc biên dịch đúng lúc một phần được sử dụng cho nhiều ngôn ngữ từng được coi là "diễn giải", ví dụ như JavaScript.


5
Ngoài ra, Công cụ thực thi JavaScript V8 của Google không chỉ thực hiện biên dịch một phần chỉ trong thời gian. Nó luôn biên dịch thành mã riêng, trên thực tế, V8 thậm chí không trình thông dịch. Nó chỉ có trình biên dịch (tương tự Maxine, nhưng không giống như Maxine V8 chỉ có một trình biên dịch). Tất cả ba ví dụ này (GCJ, Maxine và V8) chứng minh quan điểm của bạn mạnh mẽ hơn nữa: không có thứ gọi là ngôn ngữ diễn giải hay ngôn ngữ được biên dịch. Một ngôn ngữ không được giải thích hoặc biên dịch. Một ngôn ngữ chỉ (Đó thực sự là một trích dẫn của Shriram Krishnamurthi).
Jörg W Mittag

3
Tại sao bạn nói về javascript trong một câu hỏi java?
Koray Tugay

1
@KorayTugay Chỉ là một ví dụ. Tôi chắc chắn không muốn ám chỉ rằng Java và Javascript có bất kỳ điểm chung nào ngoài bốn chữ cái đầu tiên của tên họ.
starblue

Ít nhất một sự khác biệt trong ngôn ngữ được dịch và biên dịch không có nghĩa là một nhị phân ngôn ngữ được biên dịch không thể thay đổi luồng thực thi bất cứ lúc nào, trong khi ngôn ngữ được dịch là rất tuân theo một số hoạt động hiện tại của các chức năng? Các thư viện trong C là tùy chọn trong khi ở các ngôn ngữ khác, bạn không thể có một đối tượng mảng mà không có phần mở rộng nhị phân C có thể được cập nhật hoặc mã hoàn toàn khác trên nền tảng khác. Ngôn ngữ Scripting sẽ có thể chạy trên cả hai trong khi ngôn ngữ được biên dịch sẽ cần một nhị phân khác để chạy
Eaton Emmerich

53

Java được biên dịch thành mã byte, sau đó đi vào Java VM, nó diễn giải nó.


33
... nhưng không hoàn toàn chính xác.
Stephen C

2
JVM có thể chọn không "diễn giải" mã byte. Nó có thể biên dịch nó và thực hiện nó trực tiếp.
Mehrdad Afshari

1
JIT không thực hiện kỹ thuật trực tiếp. Nó chỉ nhớ cách nó được thực thi.
cletus

Mehrdad: Đồng ý, tôi đã không mô tả các hoạt động JIT có thể có ở đây, vì tôi xem xét điều đó cho đến JVM và dù sao tôi cũng giữ câu trả lời của mình đơn giản :)
Noon Silk

7
cletus: Sau JIT, nó sẽ được thực thi trực tiếp. JIT đang đọc một đoạn mã byte (ví dụ: một phương thức hoàn chỉnh ) và biên dịch mã máy và nhảy tới nó.
Mehrdad Afshari

12

Java là một ngôn ngữ lập trình được biên dịch, nhưng thay vì biên dịch thẳng thành mã máy thực thi, nó biên dịch thành một dạng nhị phân trung gian gọi là mã byte JVM. Mã byte sau đó được biên dịch và / hoặc diễn giải để chạy chương trình.


11

Loại của cả hai. Đầu tiên java được biên dịch (một số người thích nói "dịch") sang mã byte, sau đó được biên dịch hoặc giải thích tùy thuộc vào tâm trạng của JIT.


32
Đó là một phần mềm tiên tiến, đã phát triển tâm trạng :)
Thorarin

5
JIT thực sự là một phần mềm rất tinh vi, có thể tối ưu hóa dựa trên thông tin thời gian chạy (như trình lược tả), điều mà trình biên dịch đi trước không thể làm được (vì nó không có thông tin về hành vi thời gian chạy của một chương trình trước thời hạn). Nhưng nó có lẽ không thực sự có tâm trạng ... :-)
Jesper

5

Java thực hiện cả biên dịch và giải thích,

Trong Java, các chương trình không được biên dịch thành các tệp thực thi ; chúng được biên dịch thành mã byte (như đã thảo luận trước đó), mà JVM (Máy ảo Java) sau đó diễn giải / thực thi khi chạy. Mã nguồn Java được biên dịch thành mã byte khi chúng tôi sử dụng trình biên dịch javac. Mã byte được lưu trên đĩa với phần mở rộng tệp. Class . .

Khi chương trình được chạy, mã byte được chuyển đổi , mã byte có thể được chuyển đổi, sử dụng trình biên dịch chỉ trong thời gian (JIT). Kết quả là mã máy sau đó được đưa vào bộ nhớ và được thực thi.

Javactrình biên dịch Java dịch mã Java thành mã byte. JVM là Máy ảo Java chạy / Phiên dịch / dịch mã byte thành mã máy gốc. Trong Java mặc dù nó được coi là ngôn ngữ được diễn giải, nó có thể sử dụng trình biên dịch JIT (Just-in-Time) khi mã byte nằm trong JVM. Trình biên dịch JIT đọc mã byte trong nhiều phần (hoặc toàn bộ, hiếm khi) và biên dịch chúng thành mã máy để chương trình có thể chạy nhanh hơn, sau đó được lưu trữ và sử dụng lại sau đó mà không cần phải biên dịch lại. Vì vậy, quá trình biên dịch JIT kết hợp tốc độ của mã được biên dịch với tính linh hoạt của diễn giải.

An ngôn ngữ diễn giải là một loại lập trình ngôn ngữ mà hầu hết các hiện thực của nó thực hiện các hướng dẫn trực tiếp và tự do, mà không trước đây soạn thảo một chương trình vào hướng dẫn ngôn ngữ máy. Trình thông dịch thực thi chương trình trực tiếp, dịch từng câu lệnh thành một chuỗi gồm một hoặc nhiều chương trình con đã được biên dịch thành mã máy.

Một ngôn ngữ biên dịch là một ngôn ngữ lập trình có triển khai thường các trình biên dịch (dịch mà tạo ra mã máy từ mã nguồn), và không dịch viên (step-by-step Chấp hành mã nguồn, nơi không có dịch pre-runtime xảy ra)

Trong các triển khai ngôn ngữ lập trình hiện đại như trong Java, ngày càng phổ biến cho một nền tảng để cung cấp cả hai tùy chọn.


Nếu được chuyển đổi, mã byte có thể được chuyển đổi, chứ không phải là được chuyển đổi. Các thông số kỹ thuật Java xác định mã byte. Cho dù mã byte đó được chạy (a) trực tiếp trong phần cứng , (b) thông qua trình thông dịch, (c) được biên dịch trước hoặc (d) được biên dịch một phần khi đang chạy đều được để lại dưới dạng chi tiết triển khai. Lưu ý rằng tất cả bốn tùy chọn đó thực sự đã được sử dụng bởi các triển khai Java trong thế giới thực khác nhau.
Basil Bourque

Cảm ơn đã chỉ ra điều này. Vậy chuyện gì sẽ xảy ra nếu mã byte không được chuyển đổi thành mã máy? Tôi có thể nghĩ về một kịch bản trong đó mã byte là tập lệnh gốc cho một số bộ xử lý và sau đó không cần chuyển đổi. Hay tôi đang thiếu một cái gì đó.
nguyên tố

Nhấp vào liên kết mà tôi đã cung cấp cho công nghệ Jazelle DBX (Direct Bytecode eXecut) , trong đó một tập hợp con của mã byte JVM hướng dẫn máy gốc của CPU (kinda-sorta). Không có điều đó, bạn nhận được mã máy được tạo từ mã byte (a) từ trình thông dịch (đang di chuyển), (b) từ trình biên dịch trước thời hạn hoặc (c) khi đang di chuyển với trình biên dịch đúng lúc ( được giải thích lúc đầu, sau đó đôi khi được biên dịch và lưu trữ trong quá trình thực thi).
Basil Bourque

-2

Java là ngôn ngữ được biên dịch theo byte nhắm vào một nền tảng được gọi là Máy ảo Java dựa trên ngăn xếp và có một số triển khai rất nhanh trên nhiều nền tảng.


1
"Biên dịch byte" nghĩa là gì?
Jesper

2
@Jesper: "Byte-comp" thường có nghĩa là "được biên dịch theo mã byte". "Mã byte" là một thuật ngữ chung bao gồm bất kỳ loại mã trung gian phi văn bản nào (thường không thể thực thi bằng máy).
Greg Hewgill

-3

Báo giá từ: https://bloss.oracle.com/ask-arun/entry/run_your_java_appluggest_faster

Các nhà phát triển ứng dụng có thể phát triển mã ứng dụng trên bất kỳ HĐH nào có sẵn trên thị trường hiện nay. Ngôn ngữ Java là bất khả tri ở giai đoạn này đối với HĐH. Mã nguồn tuyệt vời được viết bởi nhà phát triển Ứng dụng Java giờ đây được biên dịch thành mã Java Byte mà theo thuật ngữ Java được gọi là biên dịch phía Máy khách. Việc biên dịch thành mã Byte Java này là điều cho phép các nhà phát triển Java 'viết một lần'. Mã Java Byte có thể chạy trên bất kỳ HĐH và máy chủ tương thích nào, do đó làm cho mã nguồn không thể tin được của OS / Server. Đăng mã tạo Byte Java, sự tương tác giữa ứng dụng Java và OS / Server bên dưới sẽ mật thiết hơn. Cuộc hành trình tiếp tục - Khung ứng dụng doanh nghiệp thực thi các mã Java Byte này trong môi trường thời gian chạy được gọi là Máy ảo Java (JVM) hoặc Môi trường chạy thi hành Java (JRE). JVM có mối quan hệ chặt chẽ với HĐH và Phần cứng cơ bản vì nó tận dụng các tài nguyên được cung cấp bởi HĐH và Máy chủ. Mã Byte Java hiện được biên dịch thành mã thực thi ngôn ngữ máy, là nền tảng cụ thể. Điều này được gọi là biên dịch phía máy chủ.

Vì vậy, tôi muốn nói rằng Java chắc chắn là một ngôn ngữ được biên dịch.

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.