为什么在Eclipse中使用Java中的GAE中的GoogleDrive时会出现NoClassDefFoundError

为什么在Eclipse中使用Java中的GAE中的GoogleDrive时会出现NoClassDefFoundError,java,google-app-engine,Java,Google App Engine,我试图在Google App Engine(GAE)中的servlet中使用Java Google Drive API,并在Eclipse中首次将servlet加载到(localhost)服务器时获得一个NoClassDefFoundError 作为测试,我尝试在servlet中创建GoogleClientSecrets类的实例。Eclipse编译器没有抱怨,我在Java构建路径中有C:\app\gDrive\libs**google-api-client-1.16.0-rc.jar**,goo

我试图在Google App Engine(GAE)中的servlet中使用Java Google Drive API,并在Eclipse中首次将servlet加载到(localhost)服务器时获得一个NoClassDefFoundError

作为测试,我尝试在servlet中创建GoogleClientSecrets类的实例。Eclipse编译器没有抱怨,我在Java构建路径中有C:\app\gDrive\libs**google-api-client-1.16.0-rc.jar**,google-api-client-1.16.0-rc.jar包含包com.google.api.client.googleapis.auth.oauth2,其中包含GoogleClientSecrets

Eclipse中Google插件中的(localhost)服务器照常加载。当我第一次加载servlet类时(当对它发出第一个请求时),我得到NoClassDefFoundError。如果我注释掉对GoogleClientSecrets的引用,servlet工作正常

google-api-client-1.16.0-rc.jar作为外部jar文件位于Eclipse->Java构建路径的库列表中。它在Order and Export选项卡中标记为“check”(我认为这意味着jar文件应该打包在war文件中——服务器环境应该可以使用jar文件)

在运行时GAE中使用这些类是否有一些限制?对于服务器或servlet,类加载器的类路径是否有不同之处? (在一个独立的Java应用程序中,代码可以很好地访问Google Drive(即,我在Java应用程序环境中拥有所有需要的JAR——服务器中有些奇怪的东西(我认为这就是Jetty服务器)


更新DevAppServer如何查找类

(正如Mark Doyle指出的)DevAppServer的类加载方案对于加载webapp使用的类与加载DevAppServer代码本身使用的类加载方案是完全不同的——web app类加载方案不是通常的Eclipse项目构建路径过程。(为了清晰起见,我在这里记录所有这些是如何工作的,因此我可以再次找到它。)

查看它,我发现在为Web应用加载类时,DevAppServer调用Google类“IsolatedAppClassLoader”(以将每个Web应用的类加载彼此隔离。IsolatedAppClassLoader.loadClass()调用DevAppServer ClassLoader.loadClass(),这(在大多数情况下)最终调用其超类java.lang.ClassLoader.loadClass(),在本例中,该类调用java.net.URLClassLoader.findClass(),该类调用URLClassPath.getResource(),这是大部分工作的开始

URLClassPath.getResource()有一个“for”循环,用于获取URLClassPath对象中列出的每个加载程序。在这种情况下,URLClassPath中有17个(!十七个)加载程序,所有sun.misc.URLClassPath$JarLoader的实例(URLClassPath的子类).--这些似乎是DevAppServer JAR。找不到My类,将返回一个ClassNotFoundException(在此级别)

IsolatedAppClassLoader再次执行此操作(我不明白为什么,但这次直接使用URLClassLoader对象(run()方法),关于PrivilegedExceptionAction.run()??)在任何情况下,URLClassPath(来自URLClassLoader的匿名子类???)运行URLClassPath.getResource(),(这说明IsolatedAppClassLoader实例是URLClassLoader的子类!)。IsolatedAppClassLoader实例包含一个包含21个加载程序的“ucp”字段(URLClassPath子对象)

第一个是FileLoader实例(URLClassPath的子类)其中包含url文件:/C:/eclip/webAppName/war/WEB-INF/classes/——因此这是它在war/WEB-INF/classes目录中找到所有独立类的地方。剩下的20个加载程序都是JarLoader加载程序。其中15个对应于项目的war/WEB-INF目录中的15个.jar文件ning 5 JarLoader实例包括:

文件:/C:/app/eclipse/plugins/com.google.appengine.eclipse.sdkbundle_1.8.2/appengine-java-sdk-1.8.2/lib/impl/agent/appengine-agentruntime.jar/ 文件:/C:/app/eclipse/plugins/com.google.appengine.eclipse.sdkbundle_1.8.2/appengine-java-sdk-1.8.2/lib/tools/jsp/repackaged-appengine-jakarta-jstl-1.1.2.jar/ 文件:/C:/app/eclipse/plugins/com.google.appengine.eclipse.sdkbundle_1.8.2/appengine-java-sdk-1.8.2/lib/tools/jsp/repackaged-appengine-jakarta-standard-1.1.2.jar/ 文件:/C:/app/eclipse/plugins/com.google.appengine.eclipse.sdkbundle_1.8.2/appengine-java-sdk-1.8.2/lib/tools/jsp/repacked-appengine-jasper-jdt-6.0.29.jar/ 文件:/C:/app/eclipse/plugins/com.google.appengine.eclipse.sdkbundle_1.8.2/appengine-java-sdk-1.8.2/lib/opt/tools/appengine-local-endpoints/v1/appengine-local-endpoints.jar/


我不知道为什么会出现在列表上,可能是Jetty的一些标准配置?

GAE开发服务器(Jetty)设置它自己的类路径,它不会注意您在Eclipse的构建路径中配置的内容。该类路径包括WEB-INF/lib,因此您需要确保您要使用的任何库都位于那里,类似地,您的项目中的类通常是按照WEB-INF/类构建的。它还包括所需的GAE库以及模拟生产环境所需的依赖关系

此外,GAE开发环境还提供了自己的类加载机制。这提供了对GAE库的访问,还实现了对可以访问的类的限制,这些类模仿了生产环境。例如,许多Java IO/图形类受到限制,无法使用

关于导出和打包到war文件,如果您使用Eclipse的WTP进行web开发,GAE SDK的工作方式可能与您预期的不一样。启动它时,它只会启动自定义Jetty实例并指向web文件夹。因此,如果您没有将jar库放在web-INF/lib中(类似地,如果您的类没有编译)