Чи компілює команда "java" програми Java?


145

Більшість веб-сайтів в Інтернеті кажуть:

"використовувати javacкоманду для складання .javaфайлу. Потім запустіть його за допомогою javaкоманди"

Але сьогодні я спробував запустити програму java без javacі отримав дивний результат.

Ось вміст файлу, який називається hello.java:

public class Myclass {
 public static void main(String[] args){
    System.out.println("hello world");
  }
}

Потім я побіг:

$ javac hello.java

Що дає мені цю помилку:

hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
       ^
1 error

Але коли я запускаю його без javacкоманди, вона виконується без помилок.

$ java hello.java
hello world

Чи javaкоманда також компілює програму? Якщо так, то для чого нам потрібна javacкоманда?

Версія моєї Java:

openjdk version "12.0.2" 2019-07-16
OpenJDK Runtime Environment (build 12.0.2+10)
OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode)

11
Яку версію ви використовуєте? Я думаю, що в Java 9 вони представили консоль Java, і це, можливо, ви відчули.
Матьє

6
Потрібно співставити назву класу з його ім'ям файлу - це стандарт Java. Просто змініть ім'я файлу на, Myclass.javaа потім з командного рядка скомпілюйте його так, javac Myclass.javaа потім запустіть його так java Myclass.
зніміть

6
да, до javacсих пір використовуються для компіляції , якщо ви не хочете , щоб розгорнути вихідний код, або у вас є більш ніж один файл ( документація по java: для варіанта вихідного файлу використовується тільки для запуску однієї програми вихідного файлу.)
user85421

@Matthieu вихід "java -версії": версія openjdk "12.0.2" 2019-07-16 OpenJDK середовище виконання (збірка 12.0.2 + 10) OpenJDK 64-бітний сервер VM (збірка 12.0.2 + 10, змішана режим)
milad

1
@Milad - Що відбувається, це - javac збирає джерело Java у специфічний інтерпретований байт-код JVM, і javaкоманда завантажує його всередину ClassLoader JVM.
розстебнути

Відповіді:


188

Перед Java 11, щоб запустити свій код, спершу потрібно скомпілювати його, а потім запустити його. Ось приклад:

javac test.java
java test

Оскільки Java 11, ви все одно можете робити javac+java , або ви можете запустити javaсамостійно, щоб скласти і автоматично запустити свій код. Зауважте, що жоден .classфайл не буде генерований. Ось приклад:

java test.java

Якщо ти біжиш java -help , ви побачите різні дозволені звичаї. Ось як це виглядає на моїй машині. Останнє - це те, на що ви зіткнулися: java [options] <sourcefile> [args]це "виконає одну програму-вихідний файл".

$ java -help
Usage: java [options] <mainclass> [args...]
           (to execute a class)
   or  java [options] -jar <jarfile> [args...]
           (to execute a jar file)
   or  java [options] -m <module>[/<mainclass>] [args...]
       java [options] --module <module>[/<mainclass>] [args...]
           (to execute the main class in a module)
   or  java [options] <sourcefile> [args]
           (to execute a single source-file program)

ОНОВЛЕННЯ:

Як вказував @BillK, ОП також попросила:

навіщо нам потрібна команда javac?

Причина, яка нам потрібна, javac- це створити .classфайли, щоб код можна було створити, протестувати, розподілити, запустити, поділитись тощо, як це є сьогодні. Мотивація JEP 330 полягала в тому, щоб полегшити «ранні етапи вивчення Java та при написанні невеликих корисних програм», не змінюючи інших існуючих застосувань.


49
представлено в Java 11: Що нового або / та JEP 330: запуск
однофайлових

дякую @CarlosHeuberger за додаткові деталі. Я зробив невеличкий редагувати в моїй обороні , щоб відобразити , що він був введений в Java 11
Каан

7
@Spikatrix це Java 8 (Вони скинули 1.в систему1.8 в нових версіях)
Muru

1
Ви не відповіли на питання, чому нам все-таки потрібен javac - я думаю, що java працює лише на одному файлі, який ви надаєте, і раніше складених файлах. Я вважаю, що ви повинні зібрати всі інші файли, які ви хочете використовувати, з файлу, який ви телефонуєте.
Білл К

2
Ця відповідь не стосується того, чому цей новий метод не призводить до помилки імені файлу проти імені класу, як повідомляється в javac.
sebrockm

52

Якщо ви працюєте з Java 11, є нова функція, яка дозволяє виконувати єдиний вихідний файл. Компілятор з єдиним джерелом є більш розбірливим в плані назви класу порівняно з назвою файлу, так що ви можете запустити, але не вдало компілювати.

Якщо ви переглядаєте попередню версію Java, ваша поточна hello.java не компілюється через помилки компіляції, зокрема навколо назви класу. Тож абсолютно немає можливості, щоб зателефонувавши до java hello.java, скомпонував ваш код, оскільки він не компілюється.

Здається, найбільш цілком ймовірно, що ви виконували якийсь раніше складений код під час виконання команди java.


дякую, версія java: openjdk версія "12.0.2" 2019-07-16 OpenJDK середовище виконання (збірка 12.0.2 + 10) OpenJDK 64-бітний сервер VM (збірка 12.0.2 + 10, змішаний режим)
milad

5
Перевірте Використання режиму вихідного файлу для запуску однофайлових програм вихідного коду : "Компілятор не примусово застосовує необов'язкове обмеження, визначене в кінці JLS ?? 7.6, що тип у названому пакеті повинен існувати у файлі, ім'я якого складається з назви типу, за якою слідує розширення .java. "
користувач85421

2
API сценаріїв Java та запуск однофайлової програми з вихідним кодом Java ( JEP 330 ) - це дві абсолютно окремі та абсолютно не пов'язані між собою речі.
Девід Конрад

@DavidConrad, відповідно оновив багатослівність. Дякую.
Еван

Вдячний за вхід, @TJCrowder. Але я цілком впевнений, що мав намір написати це так, як є. Крім того, друге визначення у ваших посиланнях: Проміський спосіб, що включає широкий спектр різних речей.
Еван

6

Щоб відповісти, чому дана ця помилка, ім'я класу для цього файлу повинно відповідати його basename .

У вас є два варіанти, щоб цей код працював для традиційного javac; javaпослідовність:

  1. Перейменуйте клас у public class Helloабо

  2. Перейменувати hello.javaна myclass.java.

javaІнтерпретатор Java 11 не нав'язує цю вимогу. Клас, який містить, mainможе мати будь-яке ім'я, якщо це перший клас у файлі. Це було головним чином призначене для полегшення процесу навчання для початківців, а також для того, щоб дозволити "сценарії java" за допомогою shebang ( посилання ).


5

Так, але не так, як ви, мабуть, маєте на увазі.

Коли ви використовуєте javac команду для складання .java-файлу у файл .class, вихід - це щось, що називається байт-кодом. Байт-код - це машинний код (рідні інструкції) для теоретичного ЦП, заснований на специфікації Java Virtual Machine.

Ця віртуальна специфікація процесора є середнім типом типів процесорів, які були загальними на момент написання специфікації. Через це, це дуже багато різних типів процесора, що полегшує запуск одних і тих же файлів Java .class на декількох типах процесора.

Коли Java вперше була запущена, javaкоманда читала .class файл та інтерпретувала інструкції байт-коду одна за одною, а потім відображала їх у еквівалентну нативну інструкцію для будь-якого процесора, на якому він насправді працює. Це спрацювало, але не було особливо швидко. Для вдосконалення цієї компіляції Just in Time (JIT) додано до Java Runtime.

За допомогою JIT javaкоманда бере байт-код і знову компілює його до нативних інструкцій для центрального процесора, на якому він працює. Сучасні режими виконання Java, як правило, починають інтерпретувати байт-код під час компіляції JIT у фоновому режимі та переходять до складених нативних інструкцій, коли вони будуть готові, а також перепрофілюють запущене додаток, а потім знову перекомпілюють байт-код з різною оптимізацією для отримання найкращої можливої ​​продуктивності.

EDIT (щоб заспокоїти виборців):

Тож у вашому конкретному випадку (оскільки ви використовуєте JRE, новіший ніж v11) код складається (принаймні) двічі

  1. Як єдиний .java файл для байт-коду
  2. Через компілятор JIT, як він інтерпретує байт-код (хоча для helloWorld, він може насправді не отримати час для запуску будь-якого зібраного нативного коду)

7
Це не відповідає на запитання.
Девід Конрад

2
@DavidConrad Але це так! Відповідь на "Чи компілює команда" java "програми Java?" є чудовим "так" з причин, які тут наводить hardlib: він буде складати байт-код до нативних інструкцій вчасно (для нетривіальних програм зі стандартними налаштуваннями).
Пітер -

Зараз компіляція є обов'язковою? Історично Java-байт-код може бути інтерпретований; Компіляція JIT була необов'язковою.
MSalters

Цього дня за замовчуванням увімкнено JIT (дуже довго), про що свідчить mixed-modeвихід у версії
hardillb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.