java 使用tomcat类加载器加载类,找不到加载器

合集下载

java类加载机制

java类加载机制

Java类加载器(classloader)及类加载路径简介2010-11-17 20:24:48| 分类:编程技术| 标签:java 编程|字号大中小订阅昨天,看一个build Standalone中databrusher的一个脚本,发现一个Java类似乎没有在classpath中,好像也可一直运行了。

很疑惑,问了对应的开发同学,然后自己好好看了下它的代码,才知道了原理。

命令是:$JAVA_HOME/bin/java $JAVA_OPTS com.alibaba.standalone.AppStartorcom.alibaba.intl.standalone.databrusher.Startor "$main_class" "$signal_file" "$recivers"原理是:Java根据classpath找到,com.alibaba.standalone.AppStartor这个class,运行这个class,会启动一个classloader来加载com.alibaba.intl.standalone.databrusher.Startor(在里面会指定到WORLDS-INF目录下加载类),然后com.alibaba.intl.standalone.databrusher.Startor会启动对应的"$main_class".然后,花了挺多时间好好看了一下Java的classloader,了解一下其中的原理和看了下代码。

下面也简单总结一下吧。

java虚拟机是由uncher来初始化的,也就是java(或java.exe)这个程序来做的.虚拟机按以下顺序搜索并装载所有需要的类:1,引导类:组成java平台的类,包含rt.jar和i18n.jar等基础jar包中的类.2,扩展类:使用java扩展机制的类,都是位于扩展目录($JAVA_HOME/jre/lib/ext)中的.jar档案包.3,用户类:开发者定义的类或者没有使用java扩展机制的第三方产品.你必须在命令行中使用-classpath选项或者使用CLASSPATH环境变量来确定这些类的位,或者自己写ClassLoader加载。

解决SpringBootwebSocket资源无法加载、tomcat启动报错的问题

解决SpringBootwebSocket资源无法加载、tomcat启动报错的问题

解决SpringBootwebSocket资源⽆法加载、tomcat启动报错的问题⽬录问题描述:解决⽅法⼀:(常规解决、不推荐)解决⽅法⼆:(推荐)总结:问题描述:1. 项⽬集成WebSocket,且打包发布tomcat时出现websocket is already in CLOSING or CLOSE state这样的问题,建议参考“解决⽅法⼆”,但是“解决⽅法⼀”请要了解查看 ,因为解决⽅法⼆是在⼀的基础上进⾏更正2. 如果出现javax.websocket.server.ServerContainer not available这样的错误,请参考“解决⽅法⼀”中步骤3解决⽅法⼀:(常规解决、不推荐)步骤1:在BootApplication中修改:public static void main(String[] args) {SpringApplication springApplication = new SpringApplication(BootApplication.class);springApplication.addListeners(new ApplicationPidFileWriter());ConfigurableApplicationContext applicationContext = springApplication.run(args);WebSocketServer.setApplicationContext(applicationContext);注:这⾥的WebSocketServer是指你⾃定义的websocket接受消息的服务类步骤2:修改WebSocketServerprivate static ManageUserMapper manageUserMapper;public static void setApplicationContext(ConfigurableApplicationContext applicationContext) {WebSocketServer.manageUserMapper = applicationContext.getBean(ManageUserMapper.class);}步骤3: 修改pom.xml由于我们在开发过程中,如果按照以上步骤1、2进⾏修改,⼀般不会出现问题,但是如果我们打包发布tomcat,就会出现:javax.websocket.server.ServerContainer not available这样的错误,步骤3为常规解决⼀下问题⽅式<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!-- 去除内嵌tomcat --><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency>需要去除web-starter的tomcat,因为如果不去除会导致冲突,如果出现这种问题,你还需要在websocketConfig中做如下修改:(websocket为⾃定义配置类)/*** 服务器节点** 如果使⽤独⽴的servlet容器,⽽不是直接使⽤springboot的内置容器,就不要注⼊ServerEndpointExporter,因为它将由容器⾃⼰提供和管理* @return*/@Bean@Profile("dev")public ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}在application.properties做如下配置##prod:⽣产环境 dev:开发环境(WINDOWS)spring.profiles.active=dev这⾥加⼊了@Profile("dev") 这个注解。

java运行显示“找不到或无法加载主类”

java运行显示“找不到或无法加载主类”

java运⾏显⽰“找不到或⽆法加载主类”1.由于是在运⾏阶段出现的问题,那么可能是环境变量配置不当的问题,即可能是classpath路径配置错误,⽽导致.class⽂件⽆法加载。

那么此时你可以检查是否配置好classpath路径,⼀般来说classpath路径配置如下:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; (注意前⾯的 . 以及;缺⼀不可)其中.表⽰当前路径,;表⽰分隔符。

2.如果试过了很多次,classpath也配置对了,依旧出现这个错误,注意你使⽤的测试代码,是否在某⼀个包名的下⾯;⽐如说如下测试代码:在⽂件所在的当前⽬录下,运⾏javac TestPlusPlus.java编译成功,⽣成TestPlusPlus.class⽂件,这个时候,你⽤java TestPlusPlus想运⾏程序,总会出现”找不到或⽆法加载主类“的错误。

这个时候要注意,之所以找不到,是因为TestPlusPlus在HelloWorld包名的下⾯。

解决办法:1.去掉 ”package HelloWorld;“ 重新⽤javac 编译TestPlusPlus.java,再运⾏javaTestPlusPlus就可以了。

2.新建⼀个包名⼀样的⽂件夹,在本例中,为建⽴⼀个HelloWorld的⽂件夹,把TestPlusPlus.java⽂件移到该⽬录下。

然后在HelloWorld⽂件夹的平级下,打开DOS命令窗⼝,运⾏javacHelloWorld/TestPlusPlus.java编译程序,运⾏javaHelloWorld/TestPlusPlus(或者javaHelloWorld.TestPlusPlus也可以),则可以运⾏含有包名的java程序。

注意:包名不要含有'.'(点),' '(空格)等特殊符号,这样的话命令⾏⽆法判断包名与java程序名的分割点在哪⾥,从⽽还是找到或者⽆法加载主类。

类加载器与Tomcat

类加载器与Tomcat

类加载器与TomcatTomcat基于标准的类加载,再加上自己的类加载器就形成了类加载器层次。

下图详细描述了该层次结构。

从图中可以看到,它与直接委托模型有些不一样,Common类加载器代理Server类加载器,这意味着Web应用类加载器不能访问内部Server类,而Common类加载器可以。

Tomcat与System类加载器Tomcat使用默认的System类加载器,但是Tomcat通过下面来设置CLASSPA TH环境变量:CA TALINA_HOME/bin/bootstrap.jarCA TALINA_HOME/bin/tomcat-juli.jarJA V A_HOME/lib/tools.jar由于Tomcat在上面的文件列表中设置了CLASSPATH环境变量,因此在Tomcat生命周期内,system CLASSPA TH变量会忽略。

只要用户记住Tomcat拥有自己的classpath, 独立于System的Classpath,那么用户将增加的类放置在“Tomcat Common类加载器”一节中列出的目录中,就不会有任何问题。

Bootstrap.jar文件包含了Tomcat启动时所需的类。

Tools.jar包含了javac编译器,用于在运行时编译JSP页面为class文件。

Tomcat-juli.jar用于Tomcat的Bootstrap日志中。

Tomcat Common类加载器下面讲述的是Tomcat的Common类加载器层次结构。

Common类加载器加载这些Tomcat和所有Web应用所需要的类时,它从下面路径中加载表7-1中的类文件。

CA尽管开发人员可以引用其所有的API,但是不应允许他们在CATALINA_HOME/lib下放置自己的类和JAR文件。

如果开发人员希望所有类和JAR文件对于所有Web应用程序都是可见的,那么应该把它们放置在Shared类加载器能够访问到的位置。

注意这个不适用于第三方库,例如数据库驱动。

解决classNotFound的问题的思路

解决classNotFound的问题的思路

解决classNotFound的问题的思路⽤Ctrl+Shift+t可以查看class,对于报错信息,我们把没有找到的class放到查找框⾥进⾏查看,找到之后把这个jar包放到WEB-INF的lib⽬录下,build path⼀下就可以了。

以上是在java web项⽬中,没有使⽤maven的情况可以使⽤.如果使⽤maven,有时也会碰到这种情况,原因可能是jar包冲突,也可能是tomcat缓存,还可能是jar包放到了jre的ext⽬录.分情况处理.1 tomcat缓存问题,最笨的⽅法,eclipse中project-clean,然后再选build Automatically,删除server,也就是tomcat,然后重新启动eclipse,重新添加tomcat,向tomcat容器添加项⽬.2 jar包放到了jre的ext⽬录.由于classPath的加载顺序是1)BootstrapClassLoader(启动类加载器) 负责加载$JAVA_HOME中jre/lib/rt.jar⾥所有的class,加载System.getProperty(“sun.boot.class.path”)所指定的路径或jar。

2)ExtensionClassLoader(标准扩展类加载器) 负责加载java平台中扩展功能的⼀些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定⽬录下的jar包。

载System.getProperty(“java.ext.dirs”)所指定的路径或jar。

3)AppClassLoader(系统类加载器) 负责记载classpath中指定的jar包及⽬录中class4)CustomClassLoader(⾃定义加载器) 属于应⽤程序根据⾃⾝需要⾃定义的ClassLoader,如tomcat、jboss都会根据j2ee规范⾃⾏实现如果⼀个jar包放到jre的ext⽬录,则会第⼆顺序加载,它依赖的jar包只会从BootstrapClassLoader中查找,如果依赖后⾯的加载器,也会报错。

tomcat 的热更新 原理

tomcat 的热更新 原理

tomcat 的热更新原理Tomcat的热更新原理Tomcat是一个常用的Java Web服务器,用于运行Java Web应用程序。

在开发和部署过程中,我们经常需要对应用程序进行更新和调试,而传统的方式是停止Tomcat服务,然后重新部署应用程序。

这种方式效率低下,对于大型应用程序来说,停止和启动Tomcat服务可能需要花费相当长的时间。

为了解决这个问题,Tomcat引入了热更新机制,使得我们可以在不停止Tomcat服务的情况下实现应用程序的更新。

热更新是指在运行时更新应用程序的代码和资源文件,而不需要重启服务器。

Tomcat的热更新原理主要包括以下几个方面:1. 类加载器机制:Tomcat使用自定义的类加载器来加载应用程序的类。

在热更新过程中,Tomcat会检测到类文件的变化,并使用新的类加载器加载更新后的类。

这样就实现了应用程序代码的热更新。

2. 资源文件的热更新:除了类文件外,应用程序通常还包含一些资源文件,比如配置文件、静态页面等。

Tomcat的热更新机制也支持这些资源文件的热更新。

当资源文件发生变化时,Tomcat会重新加载这些文件,使得应用程序可以立即使用最新的资源。

3. 热更新的触发机制:Tomcat提供了多种触发热更新的方式。

其中一种方式是通过修改web.xml文件中的一个特殊的Servlet参数来触发热更新。

当这个参数的值发生变化时,Tomcat会重新加载应用程序。

另一种方式是通过JMX(Java Management Extensions)来触发热更新。

通过JMX可以动态修改Tomcat的配置信息,从而触发热更新。

4. 热更新的生效范围:Tomcat的热更新机制一般只对应用程序的代码和资源文件生效,而不会影响到Tomcat本身的配置文件和其他的应用程序。

这样可以确保热更新的安全性和可靠性。

总结起来,Tomcat的热更新机制通过类加载器机制和资源文件的重新加载实现了应用程序的热更新。

理解Tomcat的WebappClassLoader(web应用类加载器)一

理解Tomcat的WebappClassLoader(web应用类加载器)一

理解Tomcat的WebappClassLoader(web应用类加载器)<一>我目前的系统可能需要自己实现类加载器,想要参考Tomcat的实现。

关于Tomcat的类加载机制,网上文章很多,当然大多都是互相copy,有价值的信息并不多,不得已我开始看Tomcat 代码,略有所得,记录起来。

主要针对WebappClassLoader。

负责Web应用的类加载的是org.apache.catalina.loader.WebappClassLoader,它几个比较重要的方法:findClass(),loadClass(),findClassInternal(),findResourceInternal().类加载器被用来加载一个类的时候,loadClass()会被调用,loadClass()则调用findClass()。

后两个方法是WebappClassLoader的私有方法,findClass()调用findClassInternal()来创建class对象,而findClassInternal()则需要findResourceInternal()来查找.class文件。

通常自己实现类记载器只要实现findclass即可,这里为了实现特殊目的而override了loadClass().下面是精简过的代码(去除了几乎全部关于log、异常和安全控制的代码):findClass:public Class findClass(String name) throws ClassNotFoundException {// 先试图自己加载类,找不到则请求parent来加载// 注意这点和java默认的双亲委托模式不同Class clazz = null;clazz = findClassInternal(name);if ((clazz == null) && hasExternalRepositories) {synchronized (this) {clazz = super.findClass(name);}}if (clazz == null) {throw new ClassNotFoundException(name);}return (clazz);}loadClass:public Class loadClass(String name, boolean resolve)throws ClassNotFoundException {Class clazz = null;// (0) 先从自己的缓存中查找,有则返回,无则继续clazz = findLoadedClass0(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}// (0.1) 再从parent的缓存中查找clazz = findLoadedClass(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}// (0.2) 缓存中没有,则首先使用system类加载器来加载clazz = system.loadClass(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}//判断是否需要先让parent代理boolean delegateLoad = delegate || filter(name);// (1) 先让parent加载,通常delegateLoad == false,即这一步不会执行if (delegateLoad) {ClassLoader loader = parent;if (loader == null)loader = system;clazz = loader.loadClass(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}}// (2) delegateLoad == false 或者parent加载失败,调用自身的加载机制clazz = findClass(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}// (3) 自己加载失败,则请求parent代理加载if (!delegateLoad) {ClassLoader loader = parent;if (loader == null)loader = system;clazz = loader.loadClass(name);if (clazz != null) {return (clazz);}}throw new ClassNotFoundException(name);}findClassInternal:protected Class findClassInternal(String name)throws ClassNotFoundException {if (!validate(name))throw new ClassNotFoundException(name);//根据类名查找资源String tempPath = name.replace('.', '/');String classPath = tempPath + ".class";ResourceEntry entry = null;entry = findResourceInternal(name, classPath);if (entry == null)throw new ClassNotFoundException(name);//如果以前已经加载成功过这个类,直接返回Class clazz = entry.loadedClass;if (clazz != null)return clazz;//以下根据找到的资源(.class文件)进行:1、定义package;2、对package安全检查;3、定义class,即创建class对象synchronized (this) {if (entry.binaryContent == null && entry.loadedClass == null)throw new ClassNotFoundException(name);// Looking up the packageString packageName = null;int pos = stIndexOf('.');if (pos != -1)packageName = name.substring(0, pos);Package pkg = null;if (packageName != null) {pkg = getPackage(packageName);// Define the package (if null)if (pkg == null) {//定义package的操作,此处省略,具体参看源码pkg = getPackage(packageName);}}if (securityManager != null) {//安全检查操作,此处省略,具体参看源码}//创建class对象并返回if (entry.loadedClass == null) {try {clazz = defineClass(name, entry.binaryContent, 0,entry.binaryContent.length,new CodeSource(entry.codeBase, entry.certificates));} catch (UnsupportedClassVersionError ucve) {throw new UnsupportedClassVersionError(ucve.getLocalizedMessage() + " " +sm.getString("webappClassLoader.wrongVersion",name));}entry.loadedClass = clazz;entry.binaryContent = null;entry.source = null;entry.codeBase = null;entry.manifest = null;entry.certificates = null;} else {clazz = entry.loadedClass;}}return clazz;}findResouceInternal():下几篇介绍WebappLoader,StandardContext,StandardWrapper,ApplicationDispatcher在类加载中的作用。

tomcat加载jar异常问题的分析与解决

tomcat加载jar异常问题的分析与解决

tomcat加载jar异常问题的分析与解决现象描述:项⽬使⽤springboot启动⼀个web项⽬,在启动阶段看到console中出现了异常“1.10.3-1.4.3\hdf5.jar 系统找不到指定的⽂件”,虽然这些异常不影响项⽬的正常运⾏,但作为⼀个严谨的技术⼈员,看到这些异常就像见到仇⼈⼀样,⼀定要除之⽽后快。

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5.jar (系统找不到指定的⽂件。

)at java.util.zip.ZipFile.open(Native Method)at java.util.zip.ZipFile.<init>(ZipFile.java:225)at java.util.zip.ZipFile.<init>(ZipFile.java:155)at java.util.jar.JarFile.<init>(JarFile.java:166)at java.util.jar.JarFile.<init>(JarFile.java:130)at pat.JreCompat.jarFileNewInstance(JreCompat.java:188)at org.apache.tomcat.util.scan.JarFileUrlJar.<init>(JarFileUrlJar.java:65)at org.apache.tomcat.util.scan.JarFactory.newInstance(JarFactory.java:49)at org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:374)at org.apache.tomcat.util.scan.StandardJarScanner.processURLs(StandardJarScanner.java:309)at org.apache.tomcat.util.scan.StandardJarScanner.doScanClassPath(StandardJarScanner.java:266)at org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:229)at org.apache.jasper.servlet.TldScanner.scanJars(TldScanner.java:262)at org.apache.jasper.servlet.TldScanner.scan(TldScanner.java:104)at org.apache.jasper.servlet.JasperInitializer.onStartup(JasperInitializer.java:101)at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5204)at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421)at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411)at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)at java.util.concurrent.FutureTask.run(FutureTask.java)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)at ng.Thread.run(Thread.java:748)2019-03-29 18:09:08.303 WARN 16940 --- [ost-startStop-1] o.a.tomcat.util.scan.StandardJarScanner : Failed to scan [file:/D:/.m2/repository/org/bytedeco/javacpp-presets/hdf5-platform/1.10.3-1.4.3/hdf5-linux-x86.jar] from classloader hierarchy java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5-linux-x86.jar (系统找不到指定的⽂件。

Java找不到或无法加载主类的修复方法

Java找不到或无法加载主类的修复方法

Java找不到或⽆法加载主类的修复⽅法有时,当我们运⾏Java程序时,我们可能会看到“找不到或⽆法加载主类”。

原因很容易猜测:JVM找不到主类并给出了这个错误。

但是为什么不能呢?在本⽂中,我们将讨论找不到主类的可能原因。

另外,我们将看看如何修复它们。

⽰例程序我们将从HelloWorld程序开始:public class HelloWorld {public static void main(String[] args) {System.out.println("Hello world..");}}现在让我们编译它:$ javac HelloWorld.java在这⾥,编译器将为我们的程序⽣成⼀个.class⽂件。

此.class⽂件将在同⼀⽬录中⽣成。

class⽂件将与Java程序中给定的类名具有相同的名称。

这个.class⽂件是可执⾏的。

在下⾯的部分中,我们将运⾏这个.class⽂件,并尝试理解错误“找不到或加载主类”的可能原因。

错误的类名要运⾏Java编译器⽣成的.class⽂件,可以使⽤以下命令:java <.class filename>运⾏我们的程序:$ java helloworldError: Could not find or load main class helloworld是的,它失败了,错误是“Could not find or load main class helloworld”即找不到或加载主类helloworld。

如前所述,编译器将⽣成.class⽂件,其名称与程序中Java类的名称完全相同。

所以在我们的例⼦中,主类的名称是HelloWorld,⽽不是helloworld,要区分⼤⼩写。

让我们⽤正确的⽅式再试⼀次:$ java HelloWorldHello world..这次它成功地运⾏了。

⽂件扩展名要编译Java程序,必须提供⽂件名及其扩展名(.java):$ javac HelloWorld.java但是要运⾏.class⽂件,我们需要提供类名,⽽不是⽂件名。

理解Tomcat的WebappClassLoader(web应用类加载器)一

理解Tomcat的WebappClassLoader(web应用类加载器)一

理解Tomcat的WebappClassLoader(web应用类加载器)<一>我目前的系统可能需要自己实现类加载器,想要参考Tomcat的实现。

关于Tomcat的类加载机制,网上文章很多,当然大多都是互相copy,有价值的信息并不多,不得已我开始看Tomcat 代码,略有所得,记录起来。

主要针对WebappClassLoader。

负责Web应用的类加载的是org.apache.catalina.loader.WebappClassLoader,它几个比较重要的方法:findClass(),loadClass(),findClassInternal(),findResourceInternal().类加载器被用来加载一个类的时候,loadClass()会被调用,loadClass()则调用findClass()。

后两个方法是WebappClassLoader的私有方法,findClass()调用findClassInternal()来创建class对象,而findClassInternal()则需要findResourceInternal()来查找.class文件。

通常自己实现类记载器只要实现findclass即可,这里为了实现特殊目的而override了loadClass().下面是精简过的代码(去除了几乎全部关于log、异常和安全控制的代码):findClass:public Class findClass(String name) throws ClassNotFoundException {// 先试图自己加载类,找不到则请求parent来加载// 注意这点和java默认的双亲委托模式不同Class clazz = null;clazz = findClassInternal(name);if ((clazz == null) && hasExternalRepositories) {synchronized (this) {clazz = super.findClass(name);}}if (clazz == null) {throw new ClassNotFoundException(name);}return (clazz);}loadClass:public Class loadClass(String name, boolean resolve)throws ClassNotFoundException {Class clazz = null;// (0) 先从自己的缓存中查找,有则返回,无则继续clazz = findLoadedClass0(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}// (0.1) 再从parent的缓存中查找clazz = findLoadedClass(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}// (0.2) 缓存中没有,则首先使用system类加载器来加载clazz = system.loadClass(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}//判断是否需要先让parent代理boolean delegateLoad = delegate || filter(name);// (1) 先让parent加载,通常delegateLoad == false,即这一步不会执行if (delegateLoad) {ClassLoader loader = parent;if (loader == null)loader = system;clazz = loader.loadClass(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}}// (2) delegateLoad == false 或者parent加载失败,调用自身的加载机制clazz = findClass(name);if (clazz != null) {if (resolve) resolveClass(clazz);return (clazz);}// (3) 自己加载失败,则请求parent代理加载if (!delegateLoad) {ClassLoader loader = parent;if (loader == null)loader = system;clazz = loader.loadClass(name);if (clazz != null) {return (clazz);}}throw new ClassNotFoundException(name);}findClassInternal:protected Class findClassInternal(String name)throws ClassNotFoundException {if (!validate(name))throw new ClassNotFoundException(name);//根据类名查找资源String tempPath = name.replace('.', '/');String classPath = tempPath + ".class";ResourceEntry entry = null;entry = findResourceInternal(name, classPath);if (entry == null)throw new ClassNotFoundException(name);//如果以前已经加载成功过这个类,直接返回Class clazz = entry.loadedClass;if (clazz != null)return clazz;//以下根据找到的资源(.class文件)进行:1、定义package;2、对package安全检查;3、定义class,即创建class对象synchronized (this) {if (entry.binaryContent == null && entry.loadedClass == null)throw new ClassNotFoundException(name);// Looking up the packageString packageName = null;int pos = stIndexOf('.');if (pos != -1)packageName = name.substring(0, pos);Package pkg = null;if (packageName != null) {pkg = getPackage(packageName);// Define the package (if null)if (pkg == null) {//定义package的操作,此处省略,具体参看源码pkg = getPackage(packageName);}}if (securityManager != null) {//安全检查操作,此处省略,具体参看源码}//创建class对象并返回if (entry.loadedClass == null) {try {clazz = defineClass(name, entry.binaryContent, 0,entry.binaryContent.length,new CodeSource(entry.codeBase, entry.certificates));} catch (UnsupportedClassVersionError ucve) {throw new UnsupportedClassVersionError(ucve.getLocalizedMessage() + " " +sm.getString("webappClassLoader.wrongVersion",name));}entry.loadedClass = clazz;entry.binaryContent = null;entry.source = null;entry.codeBase = null;entry.manifest = null;entry.certificates = null;} else {clazz = entry.loadedClass;}}return clazz;}findResouceInternal():下几篇介绍WebappLoader,StandardContext,StandardWrapper,ApplicationDispatcher在类加载中的作用。

图解Tomcat类加载机制(阿里面试题)

图解Tomcat类加载机制(阿里面试题)

图解Tomcat 类加载机制(阿⾥⾯试题)Tomcat 的类加载机制是违反了双亲委托原则的,对于⼀些未加载的⾮基础类(Object,String 等),各个web 应⽤⾃⼰的类加载器(WebAppClassLoader)会优先加载,加载不到时再交给commonClassLoader ⾛双亲委托。

对于JVM 来说:因此,按照这个过程可以想到,如果同样在CLASSPATH 指定的⽬录中和⾃⼰⼯作⽬录中存放相同的class ,会优先加载CLASSPATH ⽬录中的⽂件。

1、既然 Tomcat 不遵循双亲委派机制,那么如果我⾃⼰定义⼀个恶意的HashMap ,会不会有风险呢?(阿⾥的⾯试官问)答: 显然不会有风险,如果有,Tomcat 都运⾏这么多年了,那群Tomcat ⼤神能不改进吗? tomcat 不遵循双亲委派机制,只是⾃定义的classLoader 顺序不同,但顶层还是相同的,还是要去顶层请求classloader.2、我们思考⼀下:Tomcat 是个web 容器, 那么它要解决什么问题:1. ⼀个web 容器可能需要部署两个应⽤程序,不同的应⽤程序可能会依赖同⼀个第三⽅类库的不同版本,不能要求同⼀个类库在同⼀个服务器只有⼀份,因此要保证每个应⽤程序的类库都是独⽴的,保证相互隔离。

2. 部署在同⼀个web 容器中相同的类库相同的版本可以共享。

否则,如果服务器有10个应⽤程序,那么要有10份相同的类库加载进虚拟机,这是扯淡的。

3. web 容器也有⾃⼰依赖的类库,不能于应⽤程序的类库混淆。

基于安全考虑,应该让容器的类库和程序的类库隔离开来。

4. web 容器要⽀持jsp 的修改,我们知道,jsp ⽂件最终也是要编译成class ⽂件才能在虚拟机中运⾏,但程序运⾏后修改jsp 已经是司空见惯的事情,否则要你何⽤? 所以,web 容器需要⽀持 jsp 修改后不⽤重启。

再看看我们的问题:Tomcat 如果使⽤默认的类加载机制⾏不⾏?答案是不⾏的。

java错误:找不到或无法加载主类

java错误:找不到或无法加载主类

java错误:找不到或⽆法加载主类
这个问题应该很常见的,笔者经常⼿⼯编译⼀些测试代码或者⼩⼯具,经常⽤到 javac和java来编译并运⾏⼀些简单的⼩⼯具。

以Hello World来测试。

HelloWorld.java
public class HelloWorld{
public static void main(String[]args)
{
System.out.println("the romatic greet of programmer all over the world:Hello World!");
}
}
以下是编译命令
尝试运⾏的时候报错
找不到类 HelloWorld。

后来经过排查,最终问题出现在classpath上⾯。

设置⽤户环境变量的时候需要在classpath前⾯添加.;
以便在查找classpath的时候也查找当前⽬录。

以下是正常运⾏的代码
如果不会修改系统环境变量,也可以在编译⽂件⾥⼿⼯设置classpath
set classpath=.;%classpath%
也可以在命令提⽰符⾥输⼊这个命令。

javac编译成功,用java运行class文件出现“找不到或无法加载主类” 的问题解决起来很简单

javac编译成功,用java运行class文件出现“找不到或无法加载主类” 的问题解决起来很简单

javac 编译成功Байду номын сангаас用 java 运行 class 文件出现“找不到或无法加载主类” 的问题解决起 来很简单
2012-06-07 09:25
javac 编译成功,用 java 运行 class 文件出现“找不到或无法加载主类” 的问题所在很简单 学习 android,顺便又学习下 java. 入门就遇到这样的问题,环境变量按网上说的配好了,直接 java 和 javac 都有提示出
来,说明没问题了,
做了一个简单 java,放在 e 盘根目录下,在 c:下操作 javac 该 java 文件成功了,但用 java 该 class 时却提示“找不到或无法加载主类” ,忙活了半天,找了些资料,发现其实很简单, 不是语句错误,是路径问题 classpath 的问题。
主要是以下两点要注意: 1、在 classpath 的最前面要加一个本目录路径,用.表示,由于后面还有 java 的 dt 和 tools 两个路径,所以.后要加;进行分隔表示。 2、更为重要的是,在 cmd 下运行 javac 和 java 的时候,必须在该 java 文件的目 录下运行,这样生成的 class 也在该目录下,java 的时候也会第一个就在本目录下找 class 文件,就不会提示找不到了。这个 cmd 运行路径由于一般不太注意,输入 cmd 就 会直接到 c:\个人文件夹下,而一般的 java 文件会用其它软件编写,放在选定的路径下, 这两个路径很少能主动重合,一运行当然找不到了,但是 javac 能认到,不知为什么 java 就提示找不到?这点有点奇怪。网上各种解决方法里很少注意到其实就是这个小问题造成 的找不到类,都想当然的以为是在 java 源文件路径下运行 java,那当然就找不到基本问 题所在了。 如果 1、2 都做了还是没变化,那就是该计算机改了环境变量后需要重新启动下让新的 设置生效,重启下即可。 解决了以上两点,就不会再提示“找不到或无法加载主类”

错误:找不到或无法加载主类

错误:找不到或无法加载主类
Welcome.java
文件内容如下:
public class Welcome { public static void main(String[] args) { System.out.println("Welcome to Core Java"); }
}
ቤተ መጻሕፍቲ ባይዱ
2. package 问题
如果类上加了 package,就需要建立对应 package 的目录。
3. 命令使用问题
第一步需要使用 javac Welcome.java ,将代码编译成字节码文件。成功编译后会生成 Welcome.class 文件。 第二步使用 java Welcome 运行,Welcome 后面不要跟 .java 或者 .class。这里的 Welcome 是 main 函数所在的类名。
登录后才能查看或发表评论立即登录或者逛逛博客园首页
错误:找不到或无法加载主类
问题描述:
在命令控制台中运行 java Welcome,显示如下错误: 错误: 找不到或无法加载主类
原因:
1. 环境变量 CLASSPATH 设置问题
在 CLASSPATH 中添加 . (英文句号),让 java 查找当前目录。

错误:找不到或无法加载主类

错误:找不到或无法加载主类

错误:找不到或⽆法加载主类
问题描述:
⼀直运⾏正常的⼀个⽂件,今天突然爆出这个错误,⼀头懵逼。

经检查,不缺少任何⽀持包,也清空了项⽬缓存,也重启了MyEclipse。

然⽽,并没有什么卵⽤。

分析原因:
查看了⽹上的说有描述,基本上没有说到问题根源。

解决办法:
第⼀步:找到Properties->Run/Debug Settings下⽂件,删除。

注意:不要尝试把TestServer(1)修改为TestServer,直接有提⽰“A 'Java Application' configuration with this name already exists”
第⼆步,删除该路径C:\Users\wushuai\Workspaces\MyEclipse for Spring 2014\.metadata\.plugins\org.eclipse.debug.core\.launches下的所有相关⽂件,重新运⾏。

注意:相关⽂件可能有unch、TestServer(1).launch、TesetServer(2).launch等等多个⽂件,需要统统删除。

第三步,删除重建这个⽂件。

精品文档java找不到或无法加载主类XXX

精品文档java找不到或无法加载主类XXX

java 找不到或无法加载主类XXX使用命令行运行Java文件时,有时会提示错误“找不到或无法加载主类XXX”,这里涉及到三个可能的原因:(1)java是环境变量JA V A_HOME、CLASSPATH、Path没有正确配置。

(2)命令行所在目录和Java文件所在目录不同。

(3)定义了包名的类,需要特殊处理1.原因(1)的解决方法在网上有很多配置Java环境变量的解决方法,原理都是一样的,这里就不再详述;2.原因(2)的解决方法当命令行所在目录和Java文件所在目录不同时,一定要给出Java文件的完整路径名称!例如:在D盘根目录下编写一个Hello.java文件,那么Hello.java的完整路径名称为D:\Hello.java。

1.打开命令行,执行javac Hello.java,报错“javac:找不到文件:Hello.java”,这是因为命令行的目录为C:\Users\Administrator,与Hello.java的目录不同,命令行javac从它的当前目录找不到Hello.java。

2.将命令行切换到D盘根目录下,执行javac Hello.java,此时没有报错,说明编译成功,然后再执行java Hello,程序成功运行。

当Java文件和命令行在同一目录下时,直接输入Java文件名称,即可成功运行。

3.那么如何在不同的目录下成功运行Java文件呢?解决方法:当Java文件和命令行在不同目录时,编译时输入Java文件的完整路径名称;执行时,因为classpath指定了Java 类的执行路径,Java类只有包含在classpath路径下才能被java命令识别,有如下两种方法:(1)通过set classpath命令设置Java类的临时执行路径(2)在系统环境变量classpath后面加上;d:;,表示搜索Java类时会从d盘目录搜索需要注意classpath在编译时是不起作用的,所以在目录不同时,无论有没有配置classpath路径,javac命令后面都要输入Java文件的完整路径名称。

JAVA_HOME,PATH和CLASSPATH的设置及“找不到或无法加载主类”的解决办法

JAVA_HOME,PATH和CLASSPATH的设置及“找不到或无法加载主类”的解决办法

JAVA_HOME,PATH和CLASSPATH的设置及“找不到或无法加载主类”的解决办法变量设置:JAVA_HOME=C:\Program Files\Java\jadk1.7.0 PATH=c:\programfiles\java\jdk1.7.0\bin;c:\progra m files\java\jdk1.7.0\jre\bin;CLASSPATH=C:\ProgramFiles\Java\jdk1.7.0\lib;C:\ProgramFiles\Java\jdk1.7.0\lib\tools.jar;我个人不推荐”.;%JAVA_HOME.................”的设置方法;注意①PATH和CLASSPATH变量值后面的“;”一定要有;②如果没有JAVA_HOME,PATH,CLASSPATH就新建然后再设置;③如果有PATH且它的值不为空,只需修改,就是在后面加上“;c:\programfiles\java\jdk1.7.0\bin;c:\program files\java\jdk1.7.0\jre\bin;”(我个人偏向于在后面加上而不是先删除后再添加其值,因为有其他的程序也有用到该变量的)④设置时以你自己的安装途径为准,(即变量值的盘符及路径以自己安装路径为准)设置完成后就可以再DOS上验证是否安装成功了,具体方法不再细说。

“找不到或无法加载主类”的解决办法出现如图情况:更改CLASSPATH的值;更改为CLASSPATH=C:\ProgramFiles\Java\jdk1.7.0\lib;C:\Program Files\Java\jdk1.7.0\lib\tools.jar;注意后面的“;”再次推荐用我上面提到的变量设置方法;因为有时用“PATH=%JAVA_HOME.................,CLASSPATH=%JAVA_HOME.................的设置”会不能成功安装jdk;更改CLASSPATH的值后就可以了。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

The Tomcat installation directory is not valid. It is missing expected file or folder common/i18n. eclipse 配置使用apache-tomcat-5.5.34时,提示如上。

换了个apache-tomcat-5.5.29 的版本。

但是加载启动项目时,出现类加载器无法加载类。

因为apache-tomcat-5.5.29 版本中缺少类加载器的类。

Caused by: ng.ClassNotFoundException: org.apache.catalina.loader.WebappLoader
在\apache-tomcat-5.5.29\conf\Catalina\localhost 下会有项目配置的比如project.xml运行生成。

这样启动的时候才会把项目加载上。

在eclipse\plugins\com.sysdeo.eclipse.tomcat_3.2.1 找到DevLoader.zip
文件夹。

1、在eclipse目录下,找到DevLoader包,位于
eclipse\plugins\com.sysdeo.eclipse.tomcat_3.2.1的DevLoader.zip
2、复制DevLoader.zip到Tomcat apache-tomcat-5.5.29 的\lib下。

3、解压缩DevLoader.zip在当前文件夹,然后把\DevLoader 下的org文件夹全部copy到\apache-tomcat-5.5.29\server\classes下。

必须是server\classes 下,而不能是apache-tomcat-5.5.29\common\classes 下。

4、这样就可以了。

tomcat\lib下的devloader.zip devloader文件夹现在都可以去掉了。

Caused by:ng.ClassNotFoundException: org.apache.catalina.loader.WebappLoader
该类在
apache-tomcat-5.5.29\server\lib\catalina.jar 下。

相关文档
最新文档