¿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 No se pudo encontrar o cargar la clase principal ...
¿Qué significa esto, qué lo causa y cómo debe solucionarse?
1270
3
La sintaxis del comando
java
.En primer lugar, hay que entender la forma correcta de lanzar un programa utilizando el comando
java
(ojavaw
). La sintaxis normal1 es esta:donde
es una opción de la línea de comandos (que comienza con un carácter "-"),
es un nombre de clase Java completamente calificado, y `` es un argumento arbitrario de la línea de comandos que se pasa a su aplicación.1 - Hay una segunda sintaxis para los archivos JAR "ejecutables" que describiré al final. El nombre completamente calificado (FQN) para la clase se escribe convencionalmente como lo haría en el código fuente de Java; por ejemplo
Sin embargo, algunas versiones del comando
java
permiten utilizar barras en lugar de puntos; por ejemploque (confusamente) parece un nombre de ruta de archivo, pero no lo es. Tenga en cuenta que el término nombre completamente cualificado es terminología estándar de Java ... no algo que me haya inventado para confundirle :-) Este es un ejemplo de cómo debería ser un comando
java
:Lo anterior hará que el comando
java
haga lo siguientecom.acme.example.ListUsers
.main
con firma, tipo de retorno y modificadores dados porpublic static void main(String[])
. (Nota, el nombre del argumento del método NO forma parte de la firma).Llame a ese método pasándole los argumentos de la línea de comandos ("fred", "joe", "bert") como
String[]
. Razones por las que Java no puede encontrar la claseCuando se obtiene el mensaje "No se pudo encontrar o cargar la clase principal...", significa que el primer paso ha fallado. El comando
java
no ha podido encontrar la clase. Y de hecho, el "..." en el mensaje será el nombre de la clase completamente calificado quejava
está buscando. Entonces, ¿por qué no puede encontrar la clase?Razón #1 - has cometido un error con el argumento classname
La primera causa probable es que hayas proporcionado un nombre de clase incorrecto. (O ... el nombre de clase correcto, pero en la forma incorrecta.) Considerando el ejemplo anterior, aquí hay una variedad de formas incorrectas de especificar el nombre de la clase:
Ejemplo #1 - un nombre de clase simple:
Cuando la clase está declarada en un paquete como
com.acme.example
, entonces debes usar el nombre completo de la clase incluyendo el nombre del paquete en el comandojava
; por ejemplo java com.acme.example.ListUserEjemplo #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 el casing incorrecto: java com.acme.example.listuser
Ejemplo #4 - un error tipográfico java com.acme.example.mistuser
Ejemplo #5 - un nombre de archivo fuente java ListUser.java
Ejemplo #6 - se olvidó el nombre de la clase por completo java muchos argumentos Razón #2 - el classpath de la aplicación está mal especificado
La segunda causa probable es que el nombre de la clase sea correcto, pero que el comando
java
no pueda encontrar la clase. Para entender esto, es necesario entender el concepto de "classpath". Esto se explica bien en la documentación de Oracle:La documentación del comando
java
Configuración del classpath.
El tutorial de Java - PATH y CLASSPATH Así que ... si ha especificado el nombre de la clase correctamente, lo siguiente que hay que comprobar es que ha especificado el classpath correctamente:
java
. 2. Comprueba que los nombres de los directorios y de los archivos JAR son correctos.java
.Tenga en cuenta que la sintaxis del classpath es diferente para Windows frente a Linux y Mac OS. (El separador del classpath es
;
en Windows y:
en los demás. Si utiliza el separador incorrecto para su plataforma, no obtendrá un mensaje de error explícito. En su lugar, obtendrá un archivo o directorio inexistente en la ruta que será ignorado silenciosamente). Razón #2a - el directorio equivocado está en el classpathCuando se pone un directorio en el classpath, éste corresponde teóricamente a la raíz del espacio de nombres cualificados. Las clases se ubican en la estructura de directorios debajo de esa raíz, mapeando el nombre completamente calificado a un nombre de ruta. Así, por ejemplo, si "/usr/local/acme/classes" está en la ruta de clases, entonces cuando la JVM busca una clase llamada
com.acme.example.Foon
, buscará un archivo ".class" con este nombre de ruta:Si hubieras puesto "/usr/local/acme/classes/com/acme/example" en el classpath, entonces la JVM no podría encontrar la clase. Razón #2b - la ruta del subdirectorio no coincide con el FQN
Si el FQN de sus clases es
com.acme.example.Foon
, entonces la JVM va a buscar "Foon.class" en el directorio "com/acme/example":com.acme.example.Foon
,/usr/local/acme/classes/com/acme/example/Foon.class
,/usr/local/acme/classes/com/acme/example/
, entonces:Notas:
La opción
-classpath
puede acortarse a-cp
en la mayoría de las versiones de Java. Compruebe las respectivas entradas del manual parajava
,javac
, etc.Piense cuidadosamente cuando elija entre nombres de ruta absolutos y relativos en los classpaths. Recuerde que un nombre de ruta relativo puede "romperse" si el directorio actual cambia.
Razón #2c - dependencias que faltan en el classpath
El classpath necesita incluir todas las otras clases (no del sistema) de las que depende su aplicación. (Las clases del sistema se localizan automáticamente, y rara vez necesitas preocuparte por esto). Para que la clase principal se cargue correctamente, la JVM necesita encontrar:
la propia clase.
todas las clases e interfaces en la jerarquía de superclases (por ejemplo, ver https://stackoverflow.com/questions/42880748)
todas las clases e interfaces a las que se hace referencia mediante declaraciones de variables o llamadas a métodos o expresiones de acceso a campos. (Nota: las especificaciones de JLS y JVM permiten cierto margen para que una JVM cargue las clases "perezosamente", y esto puede afectar a cuándo se lanza una excepción del cargador de clases). Razón #3 - la clase ha sido declarada en el paquete equivocado
Ocasionalmente ocurre que alguien pone un archivo de código fuente en la la carpeta equivocada en su árbol de código fuente, o que omiten la declaración del
paquete
. Si haces esto en un IDE, el compilador del IDE te lo dirá inmediatamente. Del mismo modo, si utiliza una herramienta de compilación de Java decente, la herramienta ejecutarájavac
de manera que detectará el problema. Sin embargo, si construyes tu código Java a mano, puedes hacerlo de tal manera que el compilador no note el problema, y el archivo ".class" resultante no esté en el lugar que esperas. ¿Sigues sin encontrar el problema?Hay muchas cosas que comprobar, y es fácil pasar por alto algo. Intenta añadir la opción
-Xdiag
a la línea de comandosjava
(como la primera cosa después dejava
). Esta opción mostrará varias cosas sobre la carga de clases, y esto puede ofrecerte pistas sobre cuál es el verdadero problema. Además, considere los posibles problemas causados por copiar y pegar caracteres invisibles o no ASCII de sitios web, documentos, etc. Y ten en cuenta los "homoglifos", cuando dos letras o símbolos parecen iguales... pero no lo son.La sintaxis
java -jar
.La sintaxis alternativa utilizada para los archivos JAR "ejecutables" es la siguiente:
por ejemplo
En este caso, el nombre de la clase de entrada (es decir,
com.acme.example.ListUser
) y el classpath se especifican en el MANIFIESTO del archivo JAR.IDEs
Un IDE Java típico tiene soporte para ejecutar aplicaciones Java en la propia JVM del IDE o en una JVM hija. Estas son generalmente inmunes a esta excepción particular, porque el IDE utiliza sus propios mecanismos para construir el classpath en tiempo de ejecución, identificar la clase principal y crear la línea de comandos
java
. Sin embargo, todavía es posible que esta excepción ocurra, si usted hace cosas a espaldas del IDE. Por ejemplo, si has configurado previamente un lanzador de aplicaciones para tu aplicación Java en Eclipse, y luego has movido el archivo JAR que contiene la clase "main" a un lugar diferente en el sistema de archivos sin decírselo a Eclipse, Eclipse lanzaría involuntariamente la JVM con un classpath incorrecto. En resumen, si tienes este problema en un IDE, comprueba cosas como el estado del IDE, referencias de proyecto rotas o configuraciones del lanzador rotas. También es posible que un IDE simplemente se confunda. Los IDEs son piezas de software enormemente complicadas que comprenden muchas partes que interactúan. Muchas de estas partes adoptan varias estrategias de almacenamiento en caché con el fin de hacer que el IDE en su conjunto responda. A veces pueden fallar, y un posible síntoma son los problemas al lanzar las aplicaciones. Si sospechas que esto puede estar ocurriendo, vale la pena probar cosas como reiniciar tu IDE y reconstruir el proyecto.Otras referencias
A veces lo que puede estar causando el problema no tiene nada que ver con la clase principal, y tuve que descubrir esto de la manera más difícil. Era una biblioteca referenciada que moví, y me dio el:
Simplemente borré esa referencia, la añadí de nuevo, y volvió a funcionar bien.
En primer lugar, establezca la ruta de acceso mediante este comando;
A continuación, debe cargar el programa. Escriba "cd (nombre de la carpeta)" en la unidad almacenada y compilarlo. Por ejemplo, si mi programa almacenado en la unidad D, escriba "D:" pulse enter y escriba " cd (nombre de la carpeta)".