Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FindBugs can't locate org.apache.bcel.classfile.ClassFormatException

I installed the Fedora 20 findbugs RPMs, and set up my Ant build.xml file thusly:

<property name="findbugs.home" location="/usr/share/findbugs"/>

<target name="findbugs" description="static bytecode analysis">
    <taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask">
    </taskdef>

    <findbugs home="${findbugs.home}" output="xml" outputFile="bcel-fb.xml">
        <sourcePath path="${src.dir}"/>
        <fileset dir="${build.dir}">
            <include name="**/*.class"/>
        </fileset>
    </findbugs>
</target>

This gives me the error:

java.lang.IllegalArgumentException: Can't find findbugs.jar in /usr/share/findbugs/lib

So I make /usr/share/findbugs/lib a symbolic link to /usr/share/java, where findbugs.jar lives. That gets me a bit further, but now it spits out:

findbugs:
 [findbugs] Executing findbugs from ant task
 [findbugs] Running FindBugs...
 [findbugs] Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/bcel/classfile/ClassFormatException

strace shows that it found and opened /usr/share/java/findbugs-bcel.jar, so I have no idea why it can't load the class. Explicitly adding /usr/share/java/findbugs-bcel.jar to the taskdef's classpath doesn't change anything.

NOTE: I'm not trying to run FindBugs on BCEL. BCEL is used by FindBugs to do its analysis, and my own code doesn't use BCEL at all.

like image 551
Matthew Cline Avatar asked Feb 15 '14 09:02

Matthew Cline


4 Answers

You need an <Auxclasspath/> subentity pointing to the classpath you used when you compiled. Findbugs uses the built *.class files, and needs the source to pinpoint in the source code where an error is, the classes you're analyzing, and the classpath to all of your third party jars to be able to understand the code:

 <findbugs
     home="${findbugs.home}" 
     output="xml" 
     outputFile="bcel-fb.xml">
     <auxClasspath refid="main.classpath"/>  <!-- Third party jars classpath   -->
     <class location="${main.destdir}"/>     <!-- Class files you're analyzing -->
     <sourcePath path="${main.srcdir}"/>     <!-- Source directory             -->
 </findbugs>

By the way, you should put the findbugs jar inside your project (My preference would be under ${basedir}/antlib/findbugs) and use that in your <taskdef/>:

<taskdef name="findbugs" 
    classname="edu.umd.cs.findbugs.anttask.FindBugsTask">
    <classpath>
       <fileset dir="${basedir}/antlib/findbugs"/>
    </classpath>
</taskdef>

This way, Findbugs is part of your project. Anyone who checks out your project will automatically have the findbugs jar and will be able to run your findbugs task without having to download the jar and installing it in $ANT_HOME/lib.

I do this with any optional Ant task jars like PMD, Checkstyle, and Ant-Contrib. It makes it much easier for others to be able to run my builds, and I spend less time trying to explain to people where they can get that jar, and how to install it. Plus, if you use a Continuous Build system like Jenkins, you don't have to futz with the server anytime you add in a new optional jar.

like image 82
David W. Avatar answered Oct 26 '22 23:10

David W.


Try using this,

Adding task definition

<taskdef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask"/>

Defining target

<property name="findbugs.home" value="/export/home/daveho/work/findbugs" />

  <target name="findbugs" depends="jar">
    <findbugs home="${findbugs.home}"
              output="xml"
              outputFile="bcel-fb.xml" >
      <auxClasspath path="${basedir}/lib/Regex.jar" />
      <sourcePath path="${basedir}/src/java" />
      <class location="${basedir}/bin/bcel.jar" />
    </findbugs>
  </target>

This target will execute FindBugs on bcel.jar, which is the Jar file produced by BCEL's build script. (By making it depend on the "jar" target, we ensure that the library is fully compiled before running FindBugs on it.) The output of FindBugs will be saved in XML format to a file called bcel-fb.xml. An auxiliary Jar file, Regex.jar, is added to the aux classpath, because it is referenced by the main BCEL library. A source path is specified so that the saved bug data will have accurate references to the BCEL source code.

For more info.

like image 35
Aditya Avatar answered Oct 26 '22 23:10

Aditya


If findbugs is not located at: <property name="findbugs.home" location="/usr/share/findbugs"/>

I would change your Ant Findbugs config to the location of the Findbug library files:

<property name="findbugs.home" location="/usr/share/java"/> Or even, <property name="findbugs.home" location="/usr/share/java/findbugs"/> is this is the directory.

It does look like a classpath issue.

like image 29
user2691041 Avatar answered Oct 26 '22 22:10

user2691041


According to Richard Fearn [1] Fedora repackages findbugs jars and modifies the way the FB library classes are loaded, so by using findbugs from fedora one must use workaround described below. See also [2] for the original bug request at findbugs.

Quote from [1]:

As a workaround it's possible to do this:

<findbugs classpath="/usr/share/java/findbugs.jar:/usr/share/java/ant/ant-findbugs.jar:/usr/share/java/apache-commons-lang.jar:/usr/share/java/dom4j.jar:/usr/share/java/findbugs-bcel.jar:/usr/share/java/jaxen.jar:/usr/share/java/jcip-annotations.jar:/usr/share/java/jFormatString.jar:/usr/share/java/jsr-305.jar:/usr/share/java/junit.jar:/usr/share/java/objectweb-asm/asm.jar:/usr/share/java/objectweb-asm/asm-commons.jar:/usr/share/java/objectweb-asm/asm-tree.jar">

where that classpath is the output from:

$ build-classpath cat /etc/ant.d/findbugs

[1] https://bugzilla.redhat.com/show_bug.cgi?id=1080682#c4

[2] https://sourceforge.net/p/findbugs/bugs/1255/

like image 33
Andrey Loskutov Avatar answered Oct 27 '22 00:10

Andrey Loskutov