`
mozhenghua
  • 浏览: 324811 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

maven plugin classloader加载class问题

 
阅读更多

1. 写一个基于maven的插件

今天在写基于maven plugin的一个小程序,它的功能是在maven执行package 阶段将已经打好包,从这个包中抽取分布式服务中依赖的类,之后会将这些服务器端依赖的类打成一个包。也就是执行了mvn package之后会在工程的target中生成两个jar包,一个是服务器端部署包,一个是客户端依赖包。客户端依赖包是服务器端包的一个子集。

该插件就是负责抽取服务器端部署包中的类。插件的工程名称是distribute-build,插件开发完成之后,会在具体的项目中使用,我搞了一个实验项目koubei-dian,在koubei-dian 这个分包项目中的pom中增加一个插件的配置节点,如下所示

<project></project>

<modelversion>4.0.0</modelversion>

<build></build>

.。。。。。。。。。

<plugins></plugins>

<plugin></plugin>

<groupid>com.koubei</groupid>

<artifactid>distribute-build</artifactid>

<version>1.0-SNAPSHOT</version>

<configuration></configuration>

<springconfig>dian.application.xml</springconfig>

<port>9999</port>

。。。。。。。。。

2. 发现问题

然后在dos命令行中敲入下面这个命令:

/koubei-dian>mvn com.koubei:distribute-build:distill

但是在执行distill这个goal时候出现了错误

java.lang.NoClassDefFoundError: com/koubei/util/Pager

at java.lang.Class.getDeclaredMethods0(Native Method)

at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)

at java.lang.Class.privateGetPublicMethods(Class.java:2547)

at java.lang.Class.getMethods(Class.java:1410)

at com.koubei.plugin.distribute.ClassMetaInfo.getAllDepandClass(ClassMet

aInfo.java:51)

at com.koubei.plugin.distribute.ServiceClassManager.execute(ServiceClass

Manager.java:109)

at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPlugi

nManager.java:483)

at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(Defa

ultLifecycleExecutor.java:678)

at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandalone

Goal(DefaultLifecycleExecutor.java:553)

at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(Defau

ltLifecycleExecutor.java:523)

at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHan

dleFailures(DefaultLifecycleExecutor.java:371)

at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegmen

ts(DefaultLifecycleExecutor.java:332)

at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLi

fecycleExecutor.java:181)

奇怪!我明明已经在koubeid-dian的pom中的depandance中添加了com/koubei/util/Pager 这个类所在包的依赖呀,为啥当前的classloader还是不能加载这个类呢?直觉告诉我应该是maven的classloader的加载机制的问题。于是还得依赖万能的google,终于我找到了maven reference网站上关于maven类加载机制的说明。http://maven.apache.org/guides/mini/guide-maven-classloading.html

这个文档中说了四种类加载机制,分别是:

1. System Classloader

2. Core Classloader

3. Plugin Classloaders

4. Custom Classloaders

其中我最关心的是plugin classloaders,这个类加载器从类加载的层次关系来看是继承与System classloader 和Core Classloader的,凭我想当然的理解在插件goal执行的时候插件的classloader已经包含的project pom 中申明的依赖包。但是,plugin classloader说明中有这么一句话:

Please note that the plugin classloader does neither contain the dependencies of the current project nor its build output. Instead, plugins can query the project's compile, runtime and test class path from the MavenProject in combination with the mojo annotation requiresDependencyResolution from the Mojo API Specification. For instance, flagging a mojo with @requiresDependencyResolution runtime enables it to query the runtime class path of the current project from which it could create further classloaders.

翻译一下:

请注意,plugin classloader既不包含当前工程的dependencies,也不包含当前工程的输出目录。但是,如果你现在插件运行的时候想引用当前工程的编译(compile)、运行时(runtime)、测试(test)的classpath,可以通过MavenProject 这个组合在成员对象来调用,这个mojo对象需要有“requiresDependencyResolution”这个annotation

3. 解决问题

通过以上说明,我知道解决当前maven plugin 不能正常加载类的问题可以通过两个方法解决:

方法1:在plugin配置的时候为plugin配置节点单独配置一个dependacne

<project></project>

<modelversion>4.0.0</modelversion>

<build></build>

.。。。。。。。。。

<plugins></plugins>

<plugin></plugin>

<groupid>com.koubei</groupid>

<artifactid>distribute-build</artifactid>

<version>1.0-SNAPSHOT</version>

<configuration></configuration>

<springconfig>dian.application.xml</springconfig>

<port>9999</port>

<dependencies></dependencies>

<dependency></dependency>

<groupid>com.koubei</groupid>

<artifactid>koubei-util</artifactid>

<version>1.0.0</version>

。。。。。。。。。

添加如上蓝色加粗的dependencies节点。

方法2:在plugin类中添加MavenProject 一个成员对象,然后再类级别注释上添加@requiresDependencyResolution runtime注释项

1. /**

2. * @goal extract

3. * @phase package

4. * @requiresDependencyResolution test

5. */

6. public class ServiceClassManager extends AbstractMojo {

7.

8. /**

9. * @parameter default-value="${project}"

10. * @required

11. * @readonly

12. */

13. private MavenProject project;

14.

15. public void execute() throws MojoExecutionException {

16.

17. System.out.println(project.getArtifact().getFile().getAbsolutePath());

18.

19. }

20. }

通过以上这种方式就可以达到,不需要在plugin配置节点额外添加配置依赖来达到能够取道pom compile阶段需要依赖的那些jar包了。

完。。。。

分享到:
评论
2 楼 Phoenix0101 2016-07-15  
Phoenix0101 写道
好像知道你是如何获取的maven的类加载器
我使用文件获取的类加载器是基于当前工程目录的
lib里面的东西动态获取的时候也是找不到class
Xxx.class.getClassLoader();
或者
URL url = new File("xxx").toURI().toURL();

URL url = classRootfile.toURI().toURL();

URLClassLoader loader = new URLClassLoader(new URL[] {url});
这种方式都在加载maven中的引入的jar中的class时候找不到class

是不是一定要导入maven-poject等jar
1 楼 Phoenix0101 2016-07-15  
好像知道你是如何获取的maven的类加载器
我使用文件获取的类加载器是基于当前工程目录的
lib里面的东西动态获取的时候也是找不到class
Xxx.class.getClassLoader();
或者
URL url = new File("xxx").toURI().toURL();

URL url = classRootfile.toURI().toURL();

URLClassLoader loader = new URLClassLoader(new URL[] {url});
这种方式都在加载maven中的引入的jar中的class时候找不到class

相关推荐

    xjar-maven-plugin:XJar-Maven-Plugin是对XJar的一个Maven插件封装,实现可通过Maven命令或绑定在Maven的生命周期之中执行,以更便捷的方式集成XJar

    XJar-Maven-Plugin XJar-Maven-Plugin是对的一个Maven插件封装,实现可通过Maven命令或绑定在Maven的生命周期之中执行,从而更加便捷的方式集成了 。 GitHub: : 什么是XJar XJar是基于对JAR包内部资源的加密以及...

    ClassFinal字节码加密工具-其他

    ClassFinal是一款Java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework,可避免源码泄漏或字节码被反编译。...当class被classloader加载时,真正的方法体会被解密注入。

    java class reload

    6. **使用maven的tomcat7-maven-plugin或tomcat8-maven-plugin** - Maven插件可以在开发过程中自动部署项目到Tomcat,并且在每次构建时自动更新,提供类的热替换。 7. **注意事项** - 类的热重载可能不适用于所有...

    Java之——类热加载

    在开发环境中,我们可以使用Maven的`maven-compiler-plugin`和`maven-surefire-plugin`等插件配置热加载。例如,使用`maven-surefire-plugin`的`rerunFailingTestsCount`属性可以重试失败的测试,有时这也可以达到...

    在可执行jar中载入第三方jar的几个解决方法

    这个问题通常发生在使用`Class.forName()`或`ClassLoader.getSystemClassLoader().loadClass()`尝试动态加载第三方JAR中的类时。 Java虚拟机(JVM)的类加载机制是导致此问题的关键。自JDK 1.2以来,JVM采用委托...

    通过自定义Gradle插件修改编译后的class文件

    class MyClassTransformerPlugin implements Plugin&lt;Project&gt; { void apply(Project project) { project.tasks.withType(JavaCompile) { task -&gt; task.doLast { def classLoader = new URLClassLoader(task....

    java动态加载插件化编程详解

    本文介绍了java动态加载插件化编程的知识点,包括插件化编程、Java动态加载、插件管理、插件实例化、Classloader、java.lang.Class、newInstance()、插件调用、Maven依赖、Canal、Kafka、HDFS、MySQL等。

    jar包隔离代码.zip

    1. 创建自定义ClassLoader:继承java.lang.ClassLoader,覆盖findClass方法,实现对特定jar包的加载逻辑。 2. 使用URLClassLoader:通过URL数组指定jar的路径,每个URL代表一个jar,可以控制不同版本的jar包加载顺序...

    附带资源的jar包

    当需要在运行时动态加载资源时,还可以使用`ClassLoader.getResource()`或`ClassLoader.getResourceAsStream()`,这样可以利用当前线程的上下文类加载器,适应更复杂的类加载环境。 在打包过程中,确保资源被正确...

    Tomcat优化1

    在 Tomcat 中,ClassLoader 是一个重要的组件,负责加载 Java 类。在 conf/context.xml 文件中,我们可以配置 ClassLoader 的参数,例如: ```xml ``` Server.xml 配置 在 Tomcat 中,server.xml 文件是...

    light-jpf:轻量级Java插件框架

    特点简单的API 使用自定义Java类加载器进行沙箱测试使用Maven构建插件2.用法2.1创建插件创建实现ljpf.Plugin接口的Plugin类。 public class CustomPlugin implements Plugin { @Override public void load () { ... ...

    Eclipse打包成JAR包读取外部JAR包和外部配置文件(源码)

    Maven的`maven-jar-plugin`和Gradle的`jar`任务都可以配置来包含外部JAR和配置文件。 6. **运行JAR**: 打包完成后,可以使用`java -jar`命令运行JAR,确保外部JAR和配置文件在正确的位置,且类路径设置正确。 ...

    SpringBoot java-jar命令行启动原理解析

    List&lt;ClassLoader&gt; classLoaders = new ArrayList(); classLoaders.add(getClassloader()); classLoaders.add(Thread.currentThread().getContextClassLoader()); // 启动应用程序 SpringApplication ...

    java agent 使用及实现代码

    public byte[] transform(ClassLoader loader, String className, Class&lt;?&gt; classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { className ...

    对Struts2内建拦截器的知识总结以及将Struts的Jar包上传下

    在`web.xml`文件中,添加一个名为`filter-name`为`struts2`的`Filter`,并指定`struts2-convention-classloader`作为`FilterClass`。 5. 检查并配置`struts.xml`文件,这是Struts2的配置中心,定义Action、结果页面...

    spring-boot-reference.pdf

    13.2.3. Using the Spring Boot Maven Plugin 13.3. Gradle 13.4. Ant 13.5. Starters 14. Structuring Your Code 14.1. Using the “default” Package 14.2. Locating the Main Application Class 15. ...

Global site tag (gtag.js) - Google Analytics