简体   繁体   中英

ant LinkageError without includeantruntime

How can I prevent the AntClassLoader and URLClassLoader from causing a linkage error?

Due to an older project, junit and hamcrest.core are put into ANT_HOME and our build uses includeantruntime=true in order to run unit tests.

I am now working on a project built with ant where I don't want to rely on any jar files in ANT_HOME. I religiously used includeantruntime=false in all javac stanzas.

However, now that I am using hamcrest for testing, I am getting a runtime linkage error.

java.lang.LinkageError: loader constraint violation: when resolving method 
"org.junit.Assert.assertThat(Ljava/lang/Object;Lorg/hamcrest/Matcher;)V" 
the class loader (instance of org/apache/tools/ant/loader/AntClassLoader5) 
of the current class, myclass, and the class loader (instance of
java/net/URLClassLoader) for resolved class, org/junit/Assert, have different
Class objects for the type assertThat used in the signature

The runtime linkage error occurs while junit is running the tests.

I seem to have two choices, neither of which I like:

  1. Remove junit and hamcrest.core from ANT_HOME. This breaks the other project.
  2. Remove junit and hamcrest.core from the project and rely on the settings in ANT_HOME. This is what I am trying to avoid.

I would have thought that includeantruntime would have helped.

My goal would be to allow junit and hamcrest.core to remain in ANT_HOME while also including them in the project. That is, the contents of ANT_HOME should not matter.

Is there a solution to this problem?

There are two steps to solving this issue:

  1. Add <pathelement path="${java.class.path}" /> to the class path for the test environment.
  2. Add fork="true" to the attributes for the junit element. You can also choose a fork mode for the junit element. For example, I used forkmode="once" .

includeantruntime should remain false for all conditions.

Allow junit to fork explicitly separates the junit class loader from the ant class loader preventing any inadvertent associations. The java.class.path is needed to explicitly allow ant to find all the classes required to execute.

With these settings, the libraries in the ant lib directory are not used and will not interfere with JUnit testing.

Setting "includeantruntime=false" is a good thing. It forces your build to be more standalone and less dependent on the configuration of your local machine, a problem I like to call the "magic build server" (Nobody really knows how it works)

I use Apache ivy to manage my ANT classpath dependencies. The following gives an example of using jars in a local "lib" directory:

The real power of ivy is when you combine it with Maven repositories. Your source code remains portable, but doesn't have to ship with all its 3rd party jars. At first it appears daunting but it's an approach that is worth looking into. There are some things that Maven got right :-)

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM