我收到错误“无法找到或加载主类”,即使班级在那里。从this answer开始,我了解到由于缺少依赖关系,可能会找到该类,但是没有加载。
除了手动反编译类,检查它的所有依赖项,以及它们是否在类路径上,依此类推,对于每个依赖类ad无限....有没有办法确定类路径中缺少哪个类因此导致Java无法加载我的主类?
另一个问题是缺少父/接口类的问题。但我已手动检查所有祖先类是在指定的类路径上还是在JDK中,如下所示。
$ cd ~/picketbox
$ java -cp picketbox-4.1.1.Final-redhat-1.jar org.picketbox.datasource.security.SecureIdentityLoginModule HelloWorld
Error: Could not find or load main class org.picketbox.datasource.security.SecureIdentityLoginModule
$ jar xvf picketbox-4.1.1.Final-redhat-1.jar > jarxvf.txt
$ cat jarxvf.txt | grep SecureIdentityLoginModule
inflated: org/picketbox/datasource/security/SecureIdentityLoginModule.class
$ cd org/picketbox/datasource/security/
$ javap SecureIdentityLoginModule.class | grep main
public static void main(java.lang.String[]) throws java.lang.Exception;
$ javap SecureIdentityLoginModule.class | grep extends
public class org.picketbox.datasource.security.SecureIdentityLoginModule extends org.picketbox.datasource.security.AbstractPasswordCredentialLoginModule {
$ cat ~/picketbox/jarxvf.txt | grep AbstractPasswordCredentialLoginModule
inflated: org/picketbox/datasource/security/AbstractPasswordCredentialLoginModule.class
$ javap AbstractPasswordCredentialLoginModule.class | grep extends
public abstract class org.picketbox.datasource.security.AbstractPasswordCredentialLoginModule extends org.jboss.security.auth.spi.AbstractServerLoginModule {
$ cat ~/picketbox/jarxvf.txt | grep AbstractServerLoginModule
inflated: org/jboss/security/auth/spi/AbstractServerLoginModule.class
$ cd ~/picketbox/org/jboss/security/auth/spi/
$ javap AbstractServerLoginModule.class | grep implements
public abstract class org.jboss.security.auth.spi.AbstractServerLoginModule implements javax.security.auth.spi.LoginModule {
$ cd ~/rtjar
$ cp /usr/java/jdk1.8.0_141/jre/lib/rt.jar ./
$ jar xvf rt.jar | grep spi/LoginModule
extracted: javax/security/auth/spi/LoginModule.class
$ cd javax/security/auth/spi/
$ javap LoginModule.class | grep interface
public interface javax.security.auth.spi.LoginModule {
$
答案 0 :(得分:1)
创建一个帮助类:
public class Helper {
public static void main(String[] args) {
YourActualMainClass.main(args);
}
}
并尝试运行此助手类而不是YourActualMainClass
。
关键是,Helper
的继承树和其成员的签名都不依赖于有问题的类,因此加载甚至初始化都会成功,因为HotSpot的懒惰解析策略,所以它只会尝试尝试执行YourActualMainClass
方法时加载并解析Helper.main
。此时,它会抛出一个详细错误,告诉您实际上缺少哪个类。
这与链接答案中描述的行为相匹配,当使用类的继承不依赖于它时,类的使用会导致特定的错误消息。
或者,您可以尝试使用Java 9运行应用程序,因为当主类的加载失败时,它的启动程序将打印原因。
答案 1 :(得分:0)
您可以尝试使用JVMTI显示引发的所有异常。从Identifying exceptions through JVMTI开始。只需使用以下更新的agent.c源代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jni.h>
#include <jvmti.h>
#define CHECK_JVMTI_ERROR(x,call) \
{ if (x != JVMTI_ERROR_NONE) { fprintf (stderr, "Error during %s in %s:%d\n", #call, __FILE__, __LINE__); } }
/* Global static data */
static jvmtiEnv *jvmti;
static void JNICALL cb_Exception (jvmtiEnv *jvmti_env, JNIEnv* jni_env,
jthread thread, jmethodID method, jlocation location, jobject exception,
jmethodID catch_method, jlocation catch_location)
{
jclass exceptionClass = (*jni_env)->GetObjectClass(jni_env, exception);
jmethodID methodId = (*jni_env)->GetMethodID(jni_env, exceptionClass,
"printStackTrace",
"()V");
(*jni_env)->CallVoidMethod(jni_env, exception, methodId);
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
jint rc;
jvmtiError r;
jvmtiCapabilities capabilities;
jvmtiEventCallbacks callbacks;
/* Get JVMTI environment */
rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION);
if (rc != JNI_OK)
{
fprintf (stderr, "Error!: Unable to create jvmtiEnv, rc=%d\n", rc);
return -1;
}
/* Get/Add JVMTI capabilities */
memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_generate_exception_events = 1;
r = (*jvmti)->AddCapabilities(jvmti, &capabilities);
CHECK_JVMTI_ERROR(r, AddCapabilities);
/* Set callbacks and enable event notifications */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.Exception = &cb_Exception;
r = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
CHECK_JVMTI_ERROR(r, SetEventCallbacks);
/* Exception events */
r = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_EXCEPTION, NULL);
CHECK_JVMTI_ERROR(r, SetEventNotificationMode);
return 0;
}
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm)
{
}