Pregunta ¿Qué significa "No se pudo encontrar o cargar la clase principal"?


Un problema común que experimentan los nuevos desarrolladores de Java es que sus programas no se ejecutan con el mensaje de error: Could not find or load main class ...

¿Qué significa esto, qué lo causa y cómo se debe solucionar?


909
2017-08-07 03:02


origen


Respuestas:


los java <class-name> sintaxis de comando

En primer lugar, debe comprender la forma correcta de iniciar un programa utilizando el java (o javaw) comando.

La sintaxis normal1 Es esto:

    java [ <option> ... ] <class-name> [<argument> ...]

dónde <option> es una opción de línea de comando (comenzando con un carácter "-"), <class-name> es un nombre de clase completo de Java, y <argument> es un argumento de línea de comando arbitrario que pasa a su aplicación.
1 - Hay una segunda sintaxis para los archivos JAR "ejecutables" que describiré en la parte inferior.

El nombre completo (FQN) para la clase se escribe convencionalmente como lo haría en el código fuente de Java; p.ej.

    packagename.packagename2.packagename3.ClassName

Sin embargo, algunas versiones de java comando le permite usar barras en lugar de puntos; p.ej.

    packagename/packagename2/packagename3/ClassName

que (confusamente) se parece a un nombre de ruta de archivo, pero no es uno. Tenga en cuenta que el término nombre completo es la terminología estándar de Java ... no es algo que inventé para confundirte :-)

Aquí hay un ejemplo de lo que java comando debería verse así:

    java -Xmx100m com.acme.example.ListUsers fred joe bert

Lo anterior va a causar la java comando para hacer lo siguiente:

  1. Busque la versión compilada de com.acme.example.ListUsers clase.
  2. Carga la clase.
  3. Verifique que la clase tenga un main método con firma, tipo de retorno y modificadores dada por public static void main(String[]). (Tenga en cuenta que el nombre del argumento del método es NO parte de la firma)
  4. Llamar a ese método pasándole los argumentos de línea de comandos ( "Joe" "Fred", "Bert") como una String[].

Razones por las cuales Java no puede encontrar la clase

Cuando aparece el mensaje "No se pudo encontrar o cargar la clase principal ...", eso significa que el primer paso ha fallado. los java comando no fue capaz de encontrar la clase. Y, de hecho, el "..." en el mensaje será el nombre de clase completamente calificado ese java está buscando.

Entonces, ¿por qué no podría encontrar la clase?

Razón n. ° 1: cometió un error con el argumento nombre de clase

La primera causa probable es que haya proporcionado el nombre de clase incorrecto. (O ... el nombre correcto de la clase, pero en la forma incorrecta.) Considerando el ejemplo anterior, aquí una variedad de formas incorrectas para especificar el nombre de clase:

  • Ejemplo # 1 - un nombre de clase simple:

    java ListUser
    

    Cuando la clase se declara en un paquete como com.acme.example, entonces debes usar el nombre de clase completo incluso el nombre del paquete en el java mando; p.ej.

    java com.acme.example.ListUser
    
  • Ejemplo # 2 - un nombre de archivo o ruta en lugar de un nombre de clase:

    java ListUser.class
    java com/acme/example/ListUser.class
    
  • Ejemplo # 3 - un nombre de clase con la carcasa incorrecta:

    java com.acme.example.listuser
    
  • Ejemplo n. ° 4: un error tipográfico

    java com.acme.example.mistuser
    
  • Ejemplo # 5 - un nombre de archivo fuente

    java ListUser.java
    
  • Ejemplo n. ° 6: olvidó por completo el nombre de la clase

    java lots of arguments
    

Motivo n. ° 2: el classpath de la aplicación está incorrectamente especificado

La segunda causa probable es que el nombre de la clase sea correcto, pero que el java comando no puede encontrar la clase. Para entender esto, necesitas entender el concepto de "classpath". Esto se explica bien por la documentación de Oracle:

Entonces ... si ha especificado el nombre de la clase correctamente, lo siguiente que debe verificar es que haya especificado la ruta de clase correctamente:

  1. Lea los tres documentos vinculados anteriormente. (Sí ... LÉALOS. Es importante que un programador de Java entiende al menos, los conceptos básicos sobre cómo funcionan los mecanismos Java classpath.)
  2. Observe la línea de comando y / o la variable de entorno CLASSPATH que está en vigencia cuando ejecuta el java mando. Verifique que los nombres de los directorios y los archivos JAR sean correctos.
  3. Si hay relativo nombres de ruta en classpath, compruebe que se resuelven correctamente ... desde el directorio actual que está en efecto cuando ejecuta el java mando.
  4. Verifique que la clase (mencionada en el mensaje de error) pueda ubicarse en el eficaz classpath.
  5. Tenga en cuenta que la sintaxis classpath es diferente para Windows versus Linux y Mac OS. (El separador classpath es ; en Windows y : en los otros.)

Razón # 2a - el directorio incorrecto está en el classpath

Cuando coloca un directorio en la ruta de clase, teóricamente corresponde a la raíz del espacio de nombre calificado. Las clases se encuentran en la estructura del directorio debajo de esa raíz, asignando el nombre completo a un nombre de ruta. Entonces, por ejemplo, si "/ usr / local / acme / classes" está en la ruta de la clase, cuando la JVM busca una clase llamada com.acme.example.Foon, buscará un archivo ".class" con este nombre de ruta:

  /usr/local/acme/classes/com/acme/example/Foon.class

Si hubiera puesto "/ usr / local / acme / classes / com / acme / example" en classpath, entonces la JVM no podría encontrar la clase.

Motivo # 2b: la ruta del subdirectorio no coincide con FQN

Si tus clases FQN son com.acme.example.Foon, entonces la JVM buscará "Foon.class" en el directorio "com / acme / example":

  • Si la estructura de su directorio no coincide con el nombre del paquete según el patrón anterior, la JVM no encontrará su clase.

  • Si intentas rebautizar una clase moviéndola, que también fallará ... pero la pila de excepción será diferente.

Para dar un ejemplo concreto, supongamos que:

  • quieres correr com.acme.example.Foon clase,
  • la ruta completa del archivo es /usr/local/acme/classes/com/acme/example/Foon.class,
  • su directorio de trabajo actual es /usr/local/acme/classes/com/acme/example/,

entonces:

# wrong, FQN is needed
java Foon

# wrong, there is no `com/acme/example` folder in the current working directory
java com.acme.example.Foon

# wrong, similar to above
java -classpath . com.acme.example.Foon

# fine; relative classpath set
java -classpath ../../.. com.acme.example.Foon

# fine; absolute classpath set
java -classpath /usr/local/acme/classes com.acme.example.Foon

Notas:

  • los -classpath la opción se puede acortar a -cp en la mayoría de los lanzamientos de Java. Verifique las entradas manuales respectivas para java, javac y así.
  • Piense detenidamente al elegir entre rutas de acceso absolutas y relativas en classpaths. Recuerde que una ruta de acceso relativa puede "romperse" si el directorio actual cambia.

Razón # 2c - dependencias que faltan en el classpath

El classpath necesita incluir todos los otro (no del sistema) clases de las que depende su aplicación. (Las clases del sistema se ubican automáticamente, y rara vez necesita preocuparse por esto). Para que la clase principal se cargue correctamente, la JVM necesita encontrar:

(Nota: las especificaciones JLS y JVM permiten que una JVM cargue las clases "de forma perezosa", y esto puede afectar cuando se lanza una excepción de cargador de clases).

Motivo n. ° 3: la clase ha sido declarada en el paquete incorrecto

Ocasionalmente sucede que alguien pone un archivo de código fuente en el la carpeta incorrecta en su árbol de código fuente, o dejan fuera el package declaración. Si haces esto en un IDE, el compilador del IDE te informará sobre esto de inmediato. Del mismo modo, si utiliza una herramienta de construcción Java decente, la herramienta se ejecutará javac de una manera que detectará el problema. Sin embargo, si construye su código Java a mano, puede hacerlo de tal manera que el compilador no advierta el problema, y ​​el archivo ".class" resultante no se encuentre en el lugar que usted espera.

Todavía no puede encontrar el problema?

Hay muchas cosas que revisar, y es fácil perderse algo. Prueba agregar el -Xdiag opción a la java línea de comando (como lo primero después java) Emitirá varias cosas sobre la carga de clases, y esto puede ofrecerte pistas sobre cuál es el verdadero problema.


los java -jar <jar file> sintaxis

La sintaxis alternativa utilizada para los archivos JAR "ejecutables" es la siguiente:

  java [ <option> ... ] -jar <jar-file-name> [<argument> ...]

p.ej.

  java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

En este caso, el nombre de la clase de punto de entrada (es decir, com.acme.example.ListUser) y classpath se especifican en MANIFEST del archivo JAR.


IDEs

Un IDE típico de Java tiene soporte para ejecutar aplicaciones Java en la propia JVM IDE o en una JVM secundaria. Estos son en general inmune a esta excepción particular, porque el IDE usa sus propios mecanismos para construir el classpath en tiempo de ejecución, identifica la clase principal y crea el java línea de comando.

Sin embargo, todavía es posible que se produzca esta excepción, si hace cosas detrás de la parte posterior del IDE. Por ejemplo, si ha configurado previamente un Lanzador de aplicaciones para su aplicación Java en Eclipse, y luego movió el archivo JAR que contiene la clase "principal" a un lugar diferente en el sistema de archivos sin decirle a Eclipse, Eclipse involuntariamente lanzaría la JVM con una ruta de clase incorrecta.

En resumen, si obtiene este problema en un IDE, compruebe si hay estado IDE obsoleto, referencias de proyecto rotas o configuraciones de iniciador rotas.

También es posible que un IDE simplemente se confunda. Los IDE son piezas de software enormemente complejas que comprenden muchas partes que interactúan. Muchas de estas partes adoptan diversas estrategias de almacenamiento en caché para hacer que el IDE en su conjunto responda. En ocasiones, esto puede ir mal, y un posible síntoma son los problemas al iniciar aplicaciones. Si sospecha que esto podría estar pasando, vale la pena reiniciar su IDE.


Otras referencias


857
2017-08-07 03:02



Si su nombre de código fuente es HelloWorld.java, su código compilado será HelloWorld.class.

Obtendrá ese error si lo llama usando:

java HelloWorld.class

En cambio, usa esto:

java HelloWorld

186
2018-05-21 11:06



Si tus clases están en paquetes, entonces tienes que cd al directorio principal y ejecutar usando el nombre completo de la clase (packageName.MainClassName).

Ejemplo:

Mis clases están aquí:

D:\project\com\cse\

El nombre completo de mi clase principal es:

com.cse.Main

Asique cd volver al directorio principal:

D:\project

Luego emita el java mando:

java com.cse.Main

95
2018-03-06 03:20



Si su método principal está en la clase en un paquete, debe ejecutarlo sobre el directorio jerárquico.

Supongamos que hay un archivo de código fuente (Main.java):

package com.test;

public class Main {

    public static void main(String[] args) {
        System.out.println("salam 2nya\n");
    }
}

Para ejecutar este código, debe colocar Main.Class en el paquete como directorio ./com/test/Main.Java. Y en el uso del directorio raíz java com.test.Main.


43
2017-10-27 12:07



Cuando el mismo código funciona en una PC, pero muestra el error en otra, la mejor solución que he encontrado es la siguiente:

javac HelloWorld.java
java -cp . HelloWorld

36
2017-08-21 06:58



Lo que me ayudó fue especificar el classpath en la línea de comando, por ejemplo:

  1. Crear una nueva carpeta, C:\temp

  2. Crear archivo Temp.java en C:\temp, con la siguiente clase en él:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
    
  3. Abra una línea de comando en la carpeta C:\tempy escriba el siguiente comando para compilar la clase Temp:

    javac Temp.java
    
  4. Ejecute la clase Java compilada, agregando el -classpath opción para que JRE sepa dónde encontrar la clase:

    java -classpath C:\temp Temp Hello!
    

26
2017-07-02 11:11



De acuerdo con el mensaje de error ("No se pudo encontrar o cargar la clase principal"), hay dos categorías de problemas:

  1. La clase principal no podría ser encontró
  2. La clase principal no podría ser cargado (este caso no se discute completamente en la respuesta aceptada)

La clase principal no podría ser encontró cuando hay error ortográfico o sintaxis incorrecta en el nombre de clase completo o no existe en el classpath proporcionado.

La clase principal no podría ser cargado cuando la clase no puede ser iniciada, por lo general, la clase principal amplía otra clase y esa clase no existe en la ruta de clase proporcionada.

Por ejemplo:

public class YourMain extends org.apache.camel.spring.Main

Si camel-spring no está incluido, este error será informado.


20
2017-09-17 01:35



A veces, lo que podría estar causando el problema no tiene nada que ver con la clase principal, y tuve que descubrirlo de la manera difícil. Era una biblioteca referenciada que moví, y me dio el:

No se pudo encontrar o cargar la clase principal xxx Linux

Acabo de eliminar esa referencia, la agregué nuevamente y funcionó bien de nuevo.


11
2017-11-01 18:04



Tuve un error en este caso:

java -cp lib.jar com.mypackage.Main

Funciona con ; para Windows y : para Unix:

java -cp lib.jar; com.mypackage.Main

11
2017-09-22 07:35



Use este comando:

java -cp . [PACKAGE.]CLASSNAME

Ejemplo: si su nombre de clase es Hello.class creado a partir de Hello.java, utilice el siguiente comando:

java -cp . Hello

Si su archivo Hello.java está dentro del paquete com.demo, utilice el siguiente comando

java -cp . com.demo.Hello

Con JDK 8 muchas veces sucede que el archivo de clase está presente en la misma carpeta, pero el java comando espera classpath y por esta razón agregamos -cp . tomar la carpeta actual como referencia para classpath.


11
2018-02-23 07:51