26.3. BCML

26.3.1. Overview

The BCML Sensor is an Ant task that sends Java structural metrics produced by BCML to the Hackystat server. The BCML sensor represents this metric data using the FileMetric sensor data type, documented in Section 25.11, “FileMetric”

BCML (the Byte Code Metric Library) is a tool for generating Java structural metrics including most of the Chidamber-Kemerer (CK) object-oriented metrics by analyzing the .class file containing the bytecode implementation of a class. Table 26.1, “BCML Metrics” lists the structural metrics gathered by the BCML sensor.

Table 26.1. BCML Metrics

MetricKeyDescription
Weighted Methods per ClassWMCCalculated with weight=1, so this metric represents the total number of methods in this class.
Depth of Inheritance TreeDITCalculated as the number of parent classes (using the extends hiearchy relation). A class that inherits from Object has DIT=0. Interface inheritance (i.e. using the extends relation) is not represented.
Number of ChildrenNOCCalculated as the number of sub-classes of this class (using the extends relation).
Coupling Between ObjectsCBOCalculated as the total number of other classes whose methods are invoked in this class.
Response for a ClassRFCCalculated as the total number of unique methods (local and external) invoked by this class.
Class size in bytesSIZEThe size of the object code representing this class (not a CK metric).
Last modified dateLastModifiedThe date and time that the .class file representing this class was generated. (Not a CK metric).
Lines of CodeLOCThe number of non-comment lines of source code, as determined from inspection of the .class file. We have found that LOC values are only approximate, and cannot be measured accurately from byte code data.

Note that the LCOM (Lack of Cohesion in Methods) CK metric is not calculated, as it is difficult to measure and has not been validated as useful for software development.

[Note]Problems with BCML

We used BCML for over a year as part of the instrumentation of the Hackystat Project, but have stopped using it due to problems with the tool. First, we found BCML analysis to add complexity to our build process, since (in our case) it required a special compilation of the each module in order to create module-specific structural metrics. Second, obtaining accurate values for DIT and NOC were not possible in our environment, since it was too difficult to make the .class files for the entire system available to the BCML processor. Third, the LOC metric was off by approximately 30%. As far as we know, this is a fundamental problem with bytecode-based generation of LOC data; it is simply not possible to generate accurate LOC data.

Other groups may find BCML of use, so we continue to provide it as an option. However, we have moved to the use LOCC for our Java structural metrics.

26.3.2. Installation

26.3.2.1. Prerequisites

The BCML sensor requires Java 1.5.0 or later and Ant 1.6.5 or later.

26.3.2.2. Download HackyInstaller and set your Hackystat Host and User Key

Follow the instructions in Chapter 2, Client-side configuration: Tool sensor installation to set your Hackystat host and user key.

26.3.2.3. Configure and install the BCML sensor

In the HackyInstaller main window, select the BCML sensor and press "Configure Selected Sensor". Figure 26.3, “ BCML installer configuration window ” shows what the configuration window should look like after the path to Ant is set, the sensor is enabled, and the "Install" button has been pressed to install the sensor.

Figure 26.3.  BCML installer configuration window


BCML installer configuration window

This sensor supports the following properties and paths:

  • Enable BCML Sensor: This property controls whether the sensor is active or not. If not checked, the sensor will not collect or send data even if installed.

  • Ant home directory: This path specifies the top-level directory for Ant. The BCML sensor requires the placement of a sensor executable into Ant's lib/ directory.

26.3.2.4. Define an Ant target that runs the BCML tool and the BCML sensor

Define a target in your build.xml file to calculate metrics from the .class files using BCML and send them to Hackystat using the bcml sensor. Example 26.4, “An example BCML target” illustrates one possible definition of such a target.

Example 26.4. An example BCML target

<target name="bcml" depends="compile" 1
 description="Runs BCML to generate source code metrics, then sends results to Hackystat.">

  <taskdef name="bcml" classname="csdl.bcml.ui.ant.BcmlTask"/>
  <taskdef name="hacky-bcml" classname="org.hackystat.sensor.bcml.BcmlSensor"/>

  <bcml todir="${build.dir}/bcml" 2
        verbose="on" 3
        aggregatefile="bcml-all.xml" 4
        fork="on"> 5
    <classpath> 6
      <path refid="compile.classpath"/>
      <pathelement location="${build.dir}/classes"/>
    </classpath>
    <fileset dir="${build.dir}/classes"> 7
      <include name="**/*.class"/>
    </fileset>
  </bcml>

  <hacky-bcml verbose="on"> 8
    <fileset dir="${build.dir}/bcml">  9
        <include name="bcml-all.xml"/>
    </fileset>
  </hacky-bcml>
</target>

Please note the following regarding Example 26.4, “An example BCML target”:

1

Specify a dependency to ensure that BCML is analyzing the latest version of the .class files.

2

The "todir" attribute specifies the directory where you wish the BCML output files to go.

3

The "verbose" attribute provides a trace of the metrics collected as BCML executes. Leave it on initially to help verify the installation.

4

The "aggregatefile" attribute names the file to be created in the todir that will contain aggregate metrics for all analyzed files.

5

If on, the BCML task runs as a separate process. This can prevent problems with other tasks that modify bytecodes during the build, such as JBlanket.

6

The "classpath" element should specify a classpath that includes all of the .class and .jar files that are needed to calculate the CK metrics (other than built-in Java classes.) This includes all of the .class files in the system to be analyzed, and typically includes all of the .class files (or their .jar container files) required to compile them. BCML will typically throw a "Class Not Found" error if the classpath element does not point to all of the .jar and .class files required for processing. Note that in order to calculate metrics like "Depth of Inheritance Tree", the system may require access to additional .class or .jar files referenced by the .class files for which metrics will be generated.

8

The "verbose" attribute provides additional execution information about the BCML sensor, such as whether the sensor is enabled, whether the data was successfully sent to the server, and so forth. Leave it on initially to help verify the installation.

9

The "fileset" element specifies the set of XML files containing BCML metric data to be sent to Hackystat. Typically, this will only indicate a single file: the aggregate file specified by the call to the bcml target.

26.3.3. Installation verification

26.3.3.1. Verify verbose mode output

To verify your BCML sensor installation, invoke the target and check to see that data is sent to the server. Example 26.5, “Example BCML output” shows the shell output from an example run with verbose= "on" for both <bcml> and <hacky-bcml>.

Example 26.5. Example BCML output

C:\cvs413\Stack>ant bcml
Buildfile: build.xml

init:

checkstyle:

compile:
    [javac] Compiling 5 source files to C:\cvs413\Stack\build\classes

bcml:
     [bcml] Defining BDT: CBO[OK] DIT[OK] LASTMOD[OK] LOC[OK] NOC[OK] RFC[OK] SIZE[OK] WMC[OK]
     [bcml] [BCML edu.hawaii.stack.ClearStack CBO:4 DIT:2 LOC:8 NOC:0 RFC:3 SIZE:691 WMC:3 LASTMOD:11/26/2004 09:34:55]
     [bcml] [BCML edu.hawaii.stack.EmptyStackException CBO:1 DIT:3 LOC:5 NOC:0 RFC:2 SIZE:456 WMC:1 LASTMOD:11/26/2004 09:34:55]
     [bcml] [BCML edu.hawaii.stack.Stack CBO:10 DIT:1 LOC:35 NOC:1 RFC:17 SIZE:2359 WMC:8 LASTMOD:11/26/2004 09:34:55]
     [bcml] [BCML edu.hawaii.stack.TestClearStack CBO:5 DIT:3 LOC:23 NOC:0 RFC:9 SIZE:1373 WMC:2 LASTMOD:11/26/2004 09:34:55]
     [bcml] [BCML edu.hawaii.stack.TestStack CBO:4 DIT:3 LOC:29 NOC:0 RFC:11 SIZE:1592 WMC:3 LASTMOD:11/26/2004 09:34:55]
     [bcml] Creating xml: C:\cvs413\Stack\build\bcml\bcml-all.xml
[hacky-bcml] Sensor enabled?: true
[hacky-bcml] Processing file: C:\cvs413\Stack\build\bcml\bcml-all.xml
[hacky-bcml] Hackystat data on 5 BCML data sent to http://localhost:8080/ (0 secs.)

BUILD SUCCESSFUL
Total time: 5 seconds

The BCML sensor will output a different message if the data was not sent successfully. The data was sent in less than a second, hence the "0 secs." output value.

26.3.3.2. List Sensor Data

Once you verify that BCML data is being sent from the client using verbose mode, login to your account on your Hackystat server, and use the "List Sensor Data" command on the Extras page to verify that FileMetric data for today's date was received by the server for the BCML tool, as illustrated in Figure 26.4, “ List Sensor Data with BCML data ”.

Figure 26.4.  List Sensor Data with BCML data


List Sensor Data with BCML data

26.3.4. Installation troubleshooting

26.3.4.1. Troubleshooting general client-server problems

The first step in troubleshooting your sensor installation is to verify that your Hackystat host and key settings are valid and that you can contact the Hackystat server, as described in Section 2.4, “HackyInstaller GUI: Setting and verifying the Hackystat host and user key”

26.3.4.2. Checking client-side logging

The BCML sensor writes out a file called bcml.0.log to the .hackystat/logs directory that can be useful in debugging your installation. Under normal conditions, this file should look similar to Example 26.6, “Log file for BCML sensor”.

Example 26.6. Log file for BCML sensor

Hackystat Version: 6.3.1119 (November 19 2004 15:22:57)
SensorShell started at: 11/28/2004 12:41:16
Type 'help' for a list of commands.
Host: http://hackystat.ics.hawaii.edu/ is available and key is valid.
Defined shell command: Activity
Defined shell command: Coverage
Defined shell command: UnitTest
Defined shell command: BuffTrans
Defined shell command: Perf
Defined shell command: Build
Defined shell command: FileMetric
#> AutoSend [10]
AutoSend OK (set to 10 minutes)
AutoSend enabled every 10 minutes.
Checking for offline data to recover.
No offline data found.
#> FileMetric [setTool, Bcml]
setTool OK
#> FileMetric [addFileMetric, Bcml, C:\cvs413\Stack\build\classes\edu\hawaii\stack\ClearStack.class, edu.hawaii.stack.ClearStack, CBO=4,DIT=2,LOC=8,NOC=0,RFC=3,SIZE=691,WMC=3,RUNTIME=1101681676910, 1100915461092]
FileMetric addData OK (1 total)

#> FileMetric [addFileMetric, Bcml, C:\cvs413\Stack\build\classes\edu\hawaii\stack\EmptyStackException.class, edu.hawaii.stack.EmptyStackException, CBO=1,DIT=3,LOC=5,NOC=0,RFC=2,SIZE=456,WMC=1,RUNTIME=1101681676910, 1100915461092]
FileMetric addData OK (2 total)

#> FileMetric [addFileMetric, Bcml, C:\cvs413\Stack\build\classes\edu\hawaii\stack\Stack.class, edu.hawaii.stack.Stack, CBO=10,DIT=1,LOC=35,NOC=1,RFC=17,SIZE=2359,WMC=8,RUNTIME=1101681676910, 1100915461092]
FileMetric addData OK (3 total)

#> FileMetric [addFileMetric, Bcml, C:\cvs413\Stack\build\classes\edu\hawaii\stack\TestClearStack.class, edu.hawaii.stack.TestClearStack, CBO=5,DIT=3,LOC=23,NOC=0,RFC=9,SIZE=1373,WMC=2,RUNTIME=1101681676910, 1100915461108]
FileMetric addData OK (4 total)

#> FileMetric [addFileMetric, Bcml, C:\cvs413\Stack\build\classes\edu\hawaii\stack\TestStack.class, edu.hawaii.stack.TestStack, CBO=4,DIT=3,LOC=29,NOC=0,RFC=11,SIZE=1592,WMC=3,RUNTIME=1101681676910, 1100915461108]
FileMetric addData OK (5 total)

#> send
Sending sensor data (11/28 12:41:17)
  Activity: Send OK (No entries to send.)
  Ping: Ping OK (contacted server http://hackystat.ics.hawaii.edu/ with valid key.)
  Coverage: Send OK (No entries to send.)
  AutoSend: AutoSend OK ('send' command ignored)
  BuffTrans: Send OK (No entries to send.)
  UnitTest: Send OK (No entries to send.)
  Build: Send OK (No entries to send.)
  Perf: Send OK (No entries to send.)
  FileMetric: Send OK (5 entries)

26.3.4.3. Submit a trouble report

If none of the above troubleshooting activities solves your problem, then you should send an email to your Hackystat Administrator to request help. Please include in your email the following information:

  • The output from 'java -version'.

  • The output from 'java -jar sensorshell.jar -verify'.

  • The contents of your sensor.properties file.

  • The contents of the bcml.0.log file.

  • A description of the problem you are having.

26.3.5. Usage tips

26.3.5.1. Integrate BCML data collection into your development process

You probably don't want to have to invoke "ant bcml" manually each time you want metric data sent to Hackystat. It is better to have the bcml data calculated and sent to Hackystat automatically as a natural course of development. One strategy is to make the bcml target a dependent target of an "install" or "distribution" target so that structural data is recorded each time significant changes occur to the system. This provides a historical record of the structural evolution that can be later used by Hackystat analyses.

26.3.5.2. Disable verbose mode

Set verbose="off" once things are working correctly.

26.3.6. Uninstallation

To disable BCML data collection temporarily, invoke HackyInstaller, bring up the BCML configuration window, and uncheck the "Enable BCML sensor" property, and apply the setting. To permanently uninstall BCML, press the "Uninstall" button and remove the BCML targets from your Ant build.xml files.