La mayoría de los sitios web en internet dicen:
"use el
javac
comando para compilar un.java
archivo. Luego ejecútelo usando eljava
comando"
Pero hoy intenté ejecutar un programa Java sin javac
y obtuve un resultado extraño.
Aquí están los contenidos de un archivo llamado hello.java
:
public class Myclass {
public static void main(String[] args){
System.out.println("hello world");
}
}
Entonces corrí:
$ javac hello.java
Lo que me da este error:
hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
^
1 error
Pero cuando lo ejecuto sin el javac
comando, se ejecutó sin ningún error.
$ java hello.java
hello world
¿El java
comando también compila el programa? En caso afirmativo, ¿por qué necesitamos el javac
comando?
La versión de mi java es:
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
y luego desde la línea de comandos compílelo asíjavac Myclass.java
y luego ejecútelo asíjava Myclass
.javac
todavía se usa para compilar si no desea implementar el código fuente, o si tiene más de un archivo ( documentación de lajava
opción para el archivo fuente: solo se usa para iniciar un solo programa de archivo fuente)javac
compila la fuente de Java en el código de bytes interpretado específico de JVM y eljava
comando lo carga dentro del ClassLoader de JVM.Respuestas:
Antes de Java 11, para ejecutar su código, primero debe compilarlo, luego puede ejecutarlo. Aquí hay un ejemplo:
Desde Java 11, aún puede hacer
javac
+java
, o puede ejecutarsejava
solo para compilar y ejecutar automáticamente su código. Tenga en cuenta que no.class
se generará ningún archivo. Aquí hay un ejemplo:Si corres
java -help
, verás los diversos usos permitidos. Así es como se ve en mi máquina. El último es con el que se topó:java [options] <sourcefile> [args]
que "ejecutará un solo programa de archivo fuente".ACTUALIZAR:
Como señaló @BillK, OP también preguntó:
La razón por la que necesitamos
javac
es crear.class
archivos para que el código se pueda crear, probar, distribuir, ejecutar, compartir, etc., como es hoy. La motivación para JEP 330 fue facilitar las "primeras etapas de aprendizaje de Java y al escribir pequeños programas de utilidad" sin cambiar ningún otro uso existente.fuente
1.
en1.8
, según la versión)javac
.Si está ejecutando Java 11, hay una nueva característica que permite la ejecución de un solo archivo fuente. El compilador de fuente única es más promiscuo en términos de nombre de clase versus nombre de archivo, por lo que así es como puede ejecutar pero no compilar correctamente.
Si está en una versión anterior de Java, entonces su hello.java actual no se compila, debido a errores de compilación, específicamente alrededor del nombre de la clase. Entonces, no hay absolutamente ninguna manera de que llamar a java hello.java compile su código, porque no se compila.
Parece muy probable que estuviera ejecutando algún código compilado previamente al ejecutar el comando java.
fuente
Para responder por qué se da este error, el nombre de la clase para el archivo debe coincidir con el del archivo
basename
.Tiene dos opciones para que este código funcione para el tradicional
javac
;java
secuencia:Cambiar el nombre de la clase a
public class Hello
oCambiar el nombre
hello.java
amyclass.java
.El
java
intérprete para Java 11 no impone este requisito. La clase que contienemain
puede tener cualquier nombre, siempre que sea la primera clase en el archivo. Esto estaba destinado principalmente a facilitar el proceso de aprendizaje para principiantes, y para permitir "scripts java" con el shebang ( ref. ).fuente
Sí, pero no de la manera que probablemente quieras decir.
Cuando utiliza el
javac
comando para compilar un archivo .java en un archivo .class, el resultado es algo llamado bytecode. Bytecode es un código de máquina (instrucciones nativas) para una CPU teórica basada en la especificación de Java Virtual Machine.Esta especificación de CPU virtual es una especie de promedio de tipos de CPU que eran comunes en el momento en que se escribió la especificación. Debido a esto, está cerca de muchos tipos diferentes de CPU, lo que facilita la ejecución de los mismos archivos Java .class en múltiples tipos de CPU.
Cuando Java se lanzó por primera vez, el
java
comando leería el archivo .class e interpretaría las instrucciones de bytecode de una en una y luego las asignaría a la instrucción nativa equivalente para la CPU en la que se estaba ejecutando. Esto funcionó pero no fue particularmente rápido. Para mejorar esto, se agregó la compilación Just in Time (JIT) a Java Runtime.Con JIT, el
java
comando toma el código de bytes y lo vuelve a compilar con las instrucciones nativas para la CPU en la que se está ejecutando. Los tiempos de ejecución modernos de Java tienden a comenzar a interpretar el código de bytes mientras compila JIT en segundo plano y cambiar a las instrucciones nativas compiladas cuando está listo y también perfilará la aplicación en ejecución y luego volverá a compilar el código de bytes con una optimización diferente para obtener el mejor rendimiento posible.EDITAR (para apaciguar a los votantes caídos):
Entonces, en su caso específico (ya que está ejecutando un JRE más nuevo que v11), el código se compila (al menos) dos veces
fuente
mixed-mode
en la salida de la versión