A maioria dos sites na internet diz:
"use o
javac
comando para compilar um.java
arquivo. Em seguida, execute-o usando ojava
comando"
Mas hoje eu tentei executar um programa java sem javac
e obtive um resultado estranho.
Aqui está o conteúdo de um arquivo chamado hello.java
:
public class Myclass {
public static void main(String[] args){
System.out.println("hello world");
}
}
Então eu corri:
$ javac hello.java
O que me dá esse erro:
hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
^
1 error
Mas quando eu o executo sem o javac
comando, ele é executado sem erros.
$ java hello.java
hello world
O java
comando também compila o programa? Se sim, por que precisamos do javac
comando?
A versão do meu 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)
Myclass.java
e, em seguida, na linha de comando, compile-o assimjavac Myclass.java
e execute-o assimjava Myclass
.javac
ainda usado para compilar se você não deseja implantar o código-fonte ou se possui mais de um único arquivo ( documentação dajava
opção para arquivo de origem: usada apenas para iniciar um único programa de arquivo-fonte.)javac
compila a fonte Java no bytecode interpretado específico da JVM e ojava
comando a carrega dentro do ClassLoader da JVM.Respostas:
Antes do Java 11, para executar seu código, você precisa primeiro compilá-lo e executá-lo. Aqui está um exemplo:
Desde o Java 11, você ainda pode executar o
javac
+java
, ou pode executarjava
sozinho para compilar e executar automaticamente o seu código. Observe que nenhum.class
arquivo será gerado. Aqui está um exemplo:Se você executar
java -help
, verá os vários usos permitidos. Aqui está o que parece na minha máquina. O último é o que você encontrou: ojava [options] <sourcefile> [args]
que "executará um único programa de arquivo de origem".ATUALIZAR:
Conforme apontado por @BillK, o OP também perguntou:
A razão pela qual precisamos
javac
é criar.class
arquivos para que o código possa ser criado, testado, distribuído, executado, compartilhado etc. como é hoje. A motivação para o JEP 330 era facilitar os "estágios iniciais do aprendizado de Java e ao escrever pequenos programas utilitários" sem alterar outros usos existentes.fonte
1.
em1.8
em versões mais recentes)javac
.Se você estiver executando o Java 11, há um novo recurso que permite a execução de arquivo de origem única. O compilador de origem única é mais promíscuo em termos de nome de classe versus nome de arquivo; é assim que você pode executar, mas não compila com êxito.
Se você estiver em uma versão anterior do Java, o hello.java atual não será compilado devido a erros de compilação, especificamente ao redor do nome da classe. Portanto, não há absolutamente nenhuma maneira de chamar java hello.java compilar seu código, porque ele não é compilado.
Parece muito provável que você estivesse executando algum código compilado anteriormente ao executar o comando java.
fonte
Para responder por que esse erro é fornecido, o nome da classe do arquivo deve corresponder ao do arquivo
basename
.Você tem duas opções para que esse código funcione para o tradicional
javac
;java
seqüência:Renomeie a classe para
public class Hello
ouRenomeie
hello.java
paramyclass.java
.O
java
intérprete para Java 11 não impõe esse requisito. A classe que contémmain
pode ter qualquer nome, desde que seja a primeira classe no arquivo. O objetivo principal era facilitar o processo de aprendizado para iniciantes e permitir "scripts java" com o shebang ( ref. ).fonte
Sim, mas não da maneira que você provavelmente quer dizer.
Quando você usa o
javac
comando para compilar um arquivo .java em um arquivo .class, a saída é algo chamado bytecode. Bytecode é o código da máquina (instruções nativas) para uma CPU teórica com base na especificação da Java Virtual Machine.Essa especificação de CPU virtual é uma espécie de média de tipos de CPUs que eram comuns no momento em que a especificação foi gravada. Por esse motivo, está próximo a muitos tipos diferentes de CPU, facilitando a execução dos mesmos arquivos Java .class em vários tipos de CPU.
Quando o Java foi iniciado pela primeira vez, o
java
comando leu o arquivo .class e interpretou as instruções do bytecode uma de cada vez e, em seguida, mapeou-as para a instrução nativa equivalente para qualquer CPU em que estivesse realmente executando. Isso funcionou, mas não foi particularmente rápido. Para melhorar essa compilação Just in Time (JIT), foi adicionado ao Java Runtime.Com o JIT, o
java
comando pega o bytecode e o compila novamente com as instruções nativas da CPU em que está sendo executado. Os tempos de execução Java modernos tendem a começar a interpretar o bytecode enquanto o JIT compila em segundo plano e alterna para as instruções nativas compiladas quando estiver pronto e também cria um perfil do aplicativo em execução e recompila o bytecode novamente com otimização diferente para obter o melhor desempenho possível.EDIT (para apaziguar os eleitores rebaixados):
Portanto, no seu caso específico (como você está executando um JRE mais recente que a v11), o código é compilado (pelo menos) duas vezes
fonte
mixed-mode
na versão