17 |
18 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | ckjm - Chidamber and Kemerer metrics for Java
2 |
3 | This directory contains the source and compiled version for
4 | a program to calculate the Chidamber and Kemerer metrics
5 | in a set of Java class files.
6 |
7 | The compiled jar file you need to extract the metrics is
8 | in the build directory. Place is in a convenient location.
9 |
10 | The build.xml file allows you to build the project from source
11 | using ant. Compilation requires Java 1.5 (J2SE5).
12 |
13 | Complete documentation, in HTML format, is in the doc directory.
14 | To print the documentation as a single document, open the
15 | file indexw.html, to browse it, open the file index.html.
16 |
17 | The project's home page is http://www.spinellis.gr/sw/ckjm
18 |
19 | Diomidis Spinellis, February 2005
20 |
--------------------------------------------------------------------------------
/.github/workflows/maven-test.yml:
--------------------------------------------------------------------------------
1 | name: Maven Test Workflow
2 |
3 |
4 | on:
5 | push:
6 | branches: [ "master" ]
7 | pull_request:
8 | branches: [ "master" ]
9 |
10 | jobs:
11 | build-and-test:
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | # Check out the code from the repository
16 | - name: Checkout repository
17 | uses: actions/checkout@v4
18 |
19 | # Set up Java with Maven
20 | - name: Set up Java
21 | uses: actions/setup-java@v4
22 | with:
23 | distribution: 'temurin' # Use Eclipse Temurin as the JDK distribution
24 | java-version: '17'
25 | cache: 'maven' # Enable caching for Maven dependencies
26 |
27 | # Build and run tests using Maven
28 | - name: Build and run tests
29 | run: mvn test
30 |
--------------------------------------------------------------------------------
/contrib/ckjm_ruby-1.0/doc/index.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
# File metrics_utils.rb, line 143
14 | defmetric_desc(sym)
15 | METRIC_DESC[sym] orraiseArgumentError, "Unknown symbol :#{sym}"
16 | end
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Chidamber and Kemerer Java Metrics
2 |
3 | [](https://zenodo.org/badge/latestdoi/3928910)
4 |
5 |
6 | The program _ckjm_ calculates Chidamber and Kemerer object-oriented metrics by processing the bytecode of compiled Java files. The program calculates for each class the following six metrics proposed by Chidamber and Kemerer.
7 |
8 | * WMC: Weighted methods per class
9 | * DIT: Depth of Inheritance Tree
10 | * NOC: Number of Children
11 | * CBO: Coupling between object classes
12 | * RFC: Response for a Class
13 | * LCOM: Lack of cohesion in methods
14 |
15 | In addition it also calculates for each class
16 |
17 | * Ca: Afferent couplings
18 | * NPM: Number of public methods
19 |
20 | If you use this tool in your research, please cite the following paper.
21 |
22 | Diomidis Spinellis. [Tool writing: A forgotten art?](http://www.spinellis.gr/pubs/jrnl/2005-IEEESW-TotT/html/v22n4.html) _IEEE Software_, 22(4):9–11, July/August 2005. [doi:10.1109/MS.2005.111](http://dx.doi.org/10.1109/MS.2005.111).
23 |
24 | Visit the project's [home page](http://www.spinellis.gr/sw/ckjm/) for more information.
25 |
--------------------------------------------------------------------------------
/contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/Plotter.src/M000004.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | new (MetricsUtils::Plotter)
9 |
10 |
11 |
12 |
13 |
# File metrics_utils.rb, line 75
14 | defprint_to_graph(plot_data)
15 | @plot_pipe.putsplot_data
16 | puts(plot_data) if$debug_mode
17 | end
18 |
19 |
--------------------------------------------------------------------------------
/src/gr/spinellis/ckjm/PrintPlainResults.java:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2005 Diomidis Spinellis, Julien Rentrop
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package gr.spinellis.ckjm;
18 |
19 | import java.io.PrintStream;
20 |
21 | /**
22 | * Simple plain text output formatter
23 | * @author Julien Rentrop
24 | */
25 | public class PrintPlainResults implements CkjmOutputHandler {
26 | private PrintStream p;
27 |
28 | public PrintPlainResults (PrintStream p) {
29 | this.p = p;
30 | }
31 |
32 | public void handleClass(String name, ClassMetrics c) {
33 | p.println(name + " " + c.toString());
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/gr/spinellis/ckjm/CkjmOutputHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2005 Diomidis Spinellis, Julien Rentrop
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package gr.spinellis.ckjm;
18 |
19 | /**
20 | * Interface of output handlers
21 | * Use this interface to couple your tool to CKJM. Example implenations
22 | * which could use this tool are ant task writing, IDE integration,
23 | * GUI based interfaces etc.
24 | *
25 | * @author Julien Rentrop
26 | */
27 | public interface CkjmOutputHandler {
28 | /**
29 | * Method called when metrics are generated
30 | * @param name Name of the class
31 | * @param c Value object that contains the corresponding metrics
32 | */
33 | void handleClass(String name, ClassMetrics c);
34 | }
35 |
--------------------------------------------------------------------------------
/contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/CKJMMetricGrapher.src/M000002.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | new (MetricsUtils::CKJMMetricGrapher)
9 |
10 |
11 |
12 |
13 |
# File metrics_utils.rb, line 160
14 | definitialize(ckjm_file_name, project_desc, plotter, jm)
15 | @ckjm_file_name, @project_desc, @plotter, @jm = ckjm_file_name, project_desc, plotter, jm
16 | end
36 |
37 |
--------------------------------------------------------------------------------
/tests/Test.java:
--------------------------------------------------------------------------------
1 | /*
2 | * ckjm test data
3 | *
4 | * $Id: \\dds\\src\\Research\\ckjm.RCS\\tests\\Test.java,v 1.2 2005/11/05 08:37:28 dds Exp $
5 | *
6 | */
7 |
8 | import java.util.*;
9 |
10 | /* NOC = 1, LCOM = 2 - 1 = 1 */
11 | class Test {
12 | int fieldname_a;
13 | int fieldname_b;
14 | int fieldname_c;
15 | int fieldname_d;
16 | int fieldname_e;
17 | int fieldname_x;
18 | int fieldname_y;
19 | int fieldname_z;
20 | String fieldname_s1;
21 | String fieldname_s2[];
22 | Set fieldname_s3;
23 | static int sa;
24 |
25 | Test() {
26 | System.out.println(
27 | fieldname_a + fieldname_b +
28 | fieldname_c + fieldname_d +
29 | fieldname_e);
30 | }
31 |
32 | int methodname_2(int i) {
33 | System.out.println("hi");
34 | return (fieldname_a + fieldname_b + fieldname_e);
35 | }
36 |
37 | AbstractCollection methodname_3(AbstractCollection a, ArrayList b[]) {
38 | System.out.println("hi");
39 | Integer i = new Integer(fieldname_x + fieldname_y + fieldname_z);
40 | return a;
41 | }
42 | }
43 |
44 | /* Coupling via extension + DIT=2 */
45 | class STest extends Test {
46 | }
47 |
48 | /* DIT=3 */
49 | class SSTest extends STest {
50 | }
51 |
52 | /* Coupling (1) via field type */
53 | class Test2 {
54 | Test a;
55 | Test b;
56 | }
57 |
58 | /* Coupling (1) via method invocation */
59 | class Test3 {
60 | int foo() { Test a = null; return a.methodname_2(1); }
61 | }
62 |
63 | /* Coupling (2) via local variable type ctor */
64 | class Test4 {
65 | void foo() { STest a = new SSTest(); a.methodname_2(4); }
66 | }
67 |
68 |
69 | /* Coupling (1) via field access */
70 | class Test5 {
71 | int foo() { return Test.sa; }
72 | }
73 |
74 | /* Coupling (1) via method return type */
75 | class Test6 {
76 | Test foo() { return null; }
77 | }
78 |
79 | /* Coupling (1) via method argument type; also public method */
80 | class Test7 {
81 | public void foo(Test a) {}
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # $Id: \\dds\\src\\Research\\ckjm.RCS\\Makefile,v 1.15 2008/04/17 08:44:48 dds Exp $
3 | #
4 |
5 | VERSION=1.9
6 | TARBALL=ckjm-$(VERSION).tar.gz
7 | ZIPBALL=ckjm-$(VERSION).zip
8 | DISTDIR=ckjm-$(VERSION)
9 | WEBDIR=$(UH)/dds/pubs/web/home/sw/ckjm
10 | SRCFILE=README.txt LICENSE.txt build.xml src/gr/spinellis/ckjm/*.java src/gr/spinellis/ckjm/ant/*.java xsl/*.xsl lib/*.txt
11 | BCEL=bcel-6.0.jar
12 | EGHTML=output_simple.html output_extra.html
13 | ART=smallpic.jpg
14 |
15 | all: antcompile
16 |
17 | antcompile:
18 | ant -Dversion=$(VERSION) -Dbcel=$(BCEL)
19 | ant -Dversion=$(VERSION) -Dbcel=$(BCEL) javadocs
20 |
21 | $(EGHTML): Makefile xsl/ckjm.xsl xsl/ckjm_extra.xsl
22 | ant -Dversion=$(VERSION) -Dbcel=$(BCEL) html
23 |
24 | $(TARBALL): docs Makefile
25 | -cmd /c rd /s/q $(DISTDIR)
26 | mkdir $(DISTDIR)
27 | mkdir $(DISTDIR)/{doc,src,lib,build,xsl}
28 | mkdir -p $(DISTDIR)/src/gr/spinellis/ckjm/ant
29 | tar cf - javadoc contrib | tar -C $(DISTDIR) -xf -
30 | cp $(WEBDIR)/doc/* $(DISTDIR)/doc
31 | cp build/ckjm-$(VERSION).jar $(DISTDIR)/build
32 | cp lib/$(BCEL) $(DISTDIR)/lib
33 | for i in $(SRCFILE) ;\
34 | do \
35 | perl -p -e 'BEGIN {binmode(STDOUT);} s/\r//' $$i >$(DISTDIR)/$$i;\
36 | done
37 | perl -p -e 'BEGIN {binmode(STDOUT);} s/\r//;print q{ } if (/VERSION/); if (/THE END/) { print qq{\n}; last;}' build.xml >$(DISTDIR)/build.xml
38 | tar czvf $(TARBALL) $(DISTDIR)
39 | zip -r $(ZIPBALL) $(DISTDIR)
40 |
41 | docs:
42 | #rm $(WEBDIR)/doc/*
43 | (cd doc && make)
44 | tar cf - javadoc | tar -C $(WEBDIR) -xf -
45 |
46 | web: $(TARBALL) $(EGHTML)
47 | cp $(ART) $(EGHTML) $(TARBALL) $(ZIPBALL) $(WEBDIR)
48 | sed "s/VERSION/$(VERSION)/g" index.html >$(WEBDIR)/index.html
49 |
50 | # A simple regression test
51 | test: antcompile
52 | jar tf test/ckjm-1.8.jar | sed -n '/\.class$$/s/^/test\/ckjm-1.8.jar /p' | java -jar build/ckjm-$(VERSION).jar >test/new.txt
53 | diff test/old.txt test/new.txt && echo OK
54 |
--------------------------------------------------------------------------------
/src/gr/spinellis/ckjm/ant/PrintXmlResults.java:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2005 Diomidis Spinellis, Julien Rentrop
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package gr.spinellis.ckjm.ant;
17 |
18 | import gr.spinellis.ckjm.CkjmOutputHandler;
19 | import gr.spinellis.ckjm.ClassMetrics;
20 |
21 | import java.io.PrintStream;
22 |
23 | /**
24 | * XML output formatter
25 | *
26 | * @author Julien Rentrop
27 | */
28 | public class PrintXmlResults implements CkjmOutputHandler {
29 | private PrintStream p;
30 |
31 | public PrintXmlResults(PrintStream p) {
32 | this.p = p;
33 | }
34 |
35 | public void printHeader() {
36 | p.println("");
37 | p.println("");
38 | }
39 |
40 | public void handleClass(String name, ClassMetrics c) {
41 | p.print("\n" +
42 | "" + name + "\n" +
43 | "" + c.getWmc() + "\n" +
44 | "" + c.getDit() + "\n" +
45 | "" + c.getNoc() + "\n" +
46 | "" + c.getCbo() + "\n" +
47 | "" + c.getRfc() + "\n" +
48 | "" + c.getLcom() + "\n" +
49 | "" + c.getCa() + "\n" +
50 | "" + c.getNpm() + "\n" +
51 | "\n");
52 | }
53 |
54 | public void printFooter () {
55 | p.println("");
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/doc/detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | The original definition of the metrics, and implementation details
4 | of both the program, and the Java language provide some leeway on
5 | how the metrics are measured.
6 | The following list contains the most important decisions.
7 | These are marked in the source code with a comment,
8 | such as the following.
9 |
10 | /* Measuring decision: couple interfaces */
11 |
12 |
13 |
Interfaces are measured when considering a class's coupling.
14 | Rationale: changes to the interface may well require changes
15 | to the class.
16 |
Use of Java SDK classes (java.*, javax.*, and some others)
17 | does not count toward a class's coupling.
18 | Rationale: the Java SDK classes are relatively stable,
19 | in comparison to the rest of the project.
20 | A command line argument switch (-s) is available for including
21 | the Java SDK classes into the calculation.
22 |
Calls to JDK methods are included in the RFC calculation.
23 | Rationale: the method calls increase the class's complexity.
24 |
The classes used for catching exceptions contribute toward the
25 | class's coupling measurements.
26 | Rationale: at the point where an exception is caught a new object
27 | of the corresponding type is instantiated.
28 |
The complexity of each method is considered 1, when calculating WMC.
29 | Rationale: ease of implementation, and compatibility with Chidamber and Kemerer.
30 |
LCOM is calculated following the 1994 paper description, and not
31 | by looking at disjoint graph components.
32 | Rationale: ease of implementation, and compatibility with Chidamber and Kemerer.
33 |
RFC is calculated up to the first method call level, and not
34 | through the transitive closure of all method calls.
35 | Rationale: ease of implementation, and compatibility with Chidamber and Kemerer.
36 |
A class's own methods contribute to its RFC.
37 | Rationale: the original Chidamber and Kemerer article describes RFC as a
38 | union of the set of methods called by the class and the set of methods in
39 | the class.
40 |
22 |
23 |
--------------------------------------------------------------------------------
/doc/oper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | To run ckjm you must run java with the -jar
4 | flag, providing as its argument the location of the file
5 | ckjm.jar.
6 | Next, you can specify as arguments the Java class files you want
7 | to analyze.
8 |
9 | Example:
10 |
11 | java -jar /usr/local/lib/ckjm-1.5.jar build/classes/gr/spinellis/ckjm/*.class
12 |
13 | (Replace the sequence /usr/local/lib/ckjm-1.5.jar
14 | with the actual path and filename of the ckjm version you are using.)
15 |
16 | The command's output will be a list of class names (prefixed by the
17 | package they are defined in), followed by the corresponding
18 | metrics for that class: WMC, DIT, NOC, CBO, RFC, LCOM, Ce, and NPM.
19 |
29 |
30 | If the classes are located in a jar archive, you can
31 | specify as a single argument the name of the archive,
32 | followed by a space, followed by the name of the class in the archive.
33 |
34 | java -jar /usr/local/lib/ckjm.jar 'ant-jai.jar org/apache/tools/ant/types/optional/image/Text.class'
35 |
36 |
37 | Finally, instead of specifying the classes to be analyszed as the
38 | command's arguments, you pass them (as class files, or as jar file, class
39 | file pairs) on the command's standard input.
40 | The following example will process all class files located in the
41 | build directory.
42 |
43 | find build -name '*.class' -print | java -jar /usr/local/lib/ckjm.jar
44 |
45 |
46 | The program, by default, will not take into account classes that belong
47 | to the Java SDK packages.
48 | The command-line option switch -s, can be used to enable this
49 | processing.
50 |
51 |
--------------------------------------------------------------------------------
/src/gr/spinellis/ckjm/ClassMetricsContainer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2005 Diomidis Spinellis
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package gr.spinellis.ckjm;
18 |
19 | import org.apache.bcel.classfile.*;
20 | import java.util.*;
21 | import java.io.*;
22 |
23 |
24 | /**
25 | * A container of class metrics mapping class names to their metrics.
26 | * This class contains the the metrics for all class's during the filter's
27 | * operation. Some metrics need to be updated as the program processes
28 | * other classes, so the class's metrics will be recovered from this
29 | * container to be updated.
30 | *
31 | * @version $Revision: 1.9 $
32 | * @author Diomidis Spinellis
33 | */
34 | class ClassMetricsContainer {
35 |
36 | /** The map from class names to the corresponding metrics */
37 | private HashMap m = new HashMap();
38 |
39 | /** Return a class's metrics */
40 | public ClassMetrics getMetrics(String name) {
41 | ClassMetrics cm = m.get(name);
42 | if (cm == null) {
43 | cm = new ClassMetrics();
44 | m.put(name, cm);
45 | }
46 | return cm;
47 | }
48 |
49 | /** Print the metrics of all the visited classes. */
50 | public void printMetrics(CkjmOutputHandler handler) {
51 | Set> entries = m.entrySet();
52 | Iterator> i;
53 |
54 | for (i = entries.iterator(); i.hasNext(); ) {
55 | Map.Entry e = i.next();
56 | ClassMetrics cm = e.getValue();
57 | if (cm.isVisited() && (MetricsFilter.includeAll() || cm.isPublic()))
58 | handler.handleClass(e.getKey(), cm);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/doc/intro.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The program ckjm calculates Chidamber and Kemerer object-oriented
5 | metrics by processing the bytecode of compiled Java files.
6 | The program calculates for each class the following six metrics, and displays
7 | them on its standard output, following the class's name:
8 |
9 |
10 |
WMC: Weighted methods per class
11 |
DIT: Depth of Inheritance Tree
12 |
NOC: Number of Children
13 |
CBO: Coupling between object classes
14 |
RFC: Response for a Class
15 |
LCOM: Lack of cohesion in methods
16 |
Ca: Afferent coupling (not a C&K metric)
17 |
NPM: Number of Public Methods for a class (not a C&K metric)
18 |
19 |
20 | I wrote this program out of frustration over the
21 | lack
22 | of reliable programs to calculate the
23 | Chidamber and Kemerer object-oriented metrics.
24 | The programs I found on the web were either
25 | incomplete (they calculated only some of the metrics),
26 | or unreliable (they calculated results that were obviously wrong),
27 | or extremely inefficient (they required GBs of RAM and hours of processing).
28 | Ckjm is mean and lean, following the Unix tradition of doing
29 | one thing well.
30 | It will not automatically recurse directories looking for the files
31 | you want measured,
32 | it does not offer a GUI and fancy diagrams (or even an XML output facility),
33 | and it calculates only few metrics other than the six ones specified
34 | by Chidamber and Kemerer.
35 | However, it does this job thoroughly, and efficiently:
36 | on a 1.6GHz Pentium-M machine version 1.1 of the tool
37 | processed the 33MB of the Eclipse 3.0
38 | jar files (19717 classes) in 95 seconds.
39 |
40 |
41 | To run the program you simply specify the class files
42 | (or pairs of jar/class files)
43 | on its command line or standard input.
44 | The program will produce on its standard output a line for each class
45 | containing the complete name of the class and the values of the corresponding
46 | class metrics.
47 | This operation model allows the tool to be easilly extended using textual
48 | pre and post processors.
49 |
50 |
51 |
--------------------------------------------------------------------------------
/doc/insel.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Using the Unix find command to select the class files
4 | to process, provides infinite flexibility.
5 |
6 |
7 | You can specify a range of modification times for the files.
8 | As an example, the following command will print the metrics of
9 | the class files modified during the last week.
10 |
11 | find build -name '*.class' -mtime -7 -print | java -jar /usr/local/lib/ckjm.jar
12 |
13 |
14 |
15 | You can filter out specific patterns, either with the GNU
16 | find's regular expression options, or by piping its results
17 | through grep.
18 | As an example, the following command will not print metrics for
19 | internal classes (their name contains a $ character).
20 |
21 | find build -name '*.class' | fgrep -v '$' | java -jar /usr/local/lib/ckjm.jar
22 |
23 |
24 |
25 | You process contents from several directories.
26 | As an example, the following command will process the class files
27 | located in the build and lib directories.
28 |
29 | find build lib -name '*.class' -print | java -jar /usr/local/lib/ckjm.jar
30 |
31 |
32 |
33 | You generate the list of class files, by processing the list of
34 | contents of a jar file.
35 | The following example will calculate the metrics for all class files
36 | located in the file ant.jar (the sed step prints only the lines
37 | ending in .class, replacing the beginning of the line with the name of the
38 | jar file, ant.jar.
39 | .
40 |
41 | jar tf ant.jar |
42 | sed -n '/\.class$/s/^/ant.jar /p' |
43 | java -jar /usr/local/lib/ckjm.jar
44 |
45 |
46 |
You can also combine the above patterns (and more)
47 | into more sophisticated file location and selection options.
48 | The following example, will process the classes of
49 | all jar files located in the lib directory.
50 |
51 | for i in lib/*.jar
52 | do
53 | jar tf $i |
54 | sed -n "/\.class$/s,^,$i ,p"
55 | done |
56 | java -jar /usr/java/ckjm-1.3/build/ckjm-1.3.jar
57 |
58 | (Replace the sequence /usr/java/ckjm-1.3/build/ckjm-1.3.jar
59 | with the actual path and filename of the ckjm version you are using.)
60 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/doc/anttask.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | First define the ant task in your build.xml file.
4 | The ckjm jar file should be in the classpath.
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | Now you can make use of the ckjm task.
14 | The attributes of the ckjm task are the following:
15 |
16 |
17 |
format
'plain' or 'xml'. Default is 'plain'
18 |
outputfile
Required. Output will be written to outputfile.
19 |
classdir
Required. Base directory which contains the class files.
20 |
21 |
22 | The ckjm
23 | task supports the nested elements <include> and <exclude>,
24 | which can be used to select the class files and the nested element
25 | <extdirs>, which is used to specify other class files participating in the
26 | inheritance hierarchy.
27 | The elements support
28 | path-like structures.
29 |
30 | Example usage:
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | You can use an XSL stylesheet to generate an HTML report from the XML
40 | output file.
41 |
42 | Example:
43 |
44 |
45 |
46 |
47 | The distribution contains in the xsl directory
48 | two sample XSL files.
49 |
50 | Here is a complete example of a build.xml file.
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | If the analyzed files form part of a class hierarchy of other class files that
76 | are not part of the analysis, then the extdirs
77 | path-like structure
78 | of the ckjm task must be set to point to the directory containing
79 | the corresponding jar files.
80 | This will internally set the java.ext.dirs property so that
81 | ckjm can locate the jar files containing those classes.
82 |
83 |
--------------------------------------------------------------------------------
/doc/ver.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Migrated source code repository to git and GitHub.
10 |
11 |
12 |
13 |
Version 1.8 2007-07-25
14 |
15 |
Contributed code contains Ruby scripts that plot ckjm metrics as charts.
16 |
The DIT calculation now also takes into account classes that are not
17 | directly processed.
18 | This may require explicitly setting up the java.ext.dirs property so that
19 | ckjm can locate the jar files containing those classes.
20 | Example:
21 |
22 | java -Djava.ext.dirs=lib -jar ckjm-1.8.jar *.class
23 |
24 | In the corresponding ant task, the new extdirs
25 | path-like structure
26 | of the ckjm task will accomplish the same function.
27 | Example:
28 |
29 |
30 |
31 |
32 |
33 |
34 | (This issue was discovered by 최재영(Choi Jae Young).)
35 |
36 |
37 |
38 |
39 |
Version 1.7 2006-04-14
40 |
41 |
Improve source code organization
42 |
Add javadoc documentation
43 |
44 |
45 |
46 |
Version 1.6 2005-11-05
47 |
48 |
Fix confusion between afferent and efferent couplings. (noted by Christian Hansen)
117 |
118 |
119 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | 4.0.0
6 |
7 | gr.spinellis
8 | ckjm
9 | 1.0-SNAPSHOT
10 |
11 | ckjm
12 | https://www.spinellis.gr/sw/ckjm/
13 |
14 |
15 | UTF-8
16 | 1.7
17 | 1.7
18 |
19 |
20 |
21 |
22 |
23 |
24 | org.apache.ant
25 | ant
26 | 1.10.11
27 |
28 |
29 |
30 |
31 | org.apache.bcel
32 | bcel
33 | 6.6.0
34 |
35 |
36 |
37 | junit
38 | junit
39 | 4.13.1
40 | test
41 |
42 |
43 |
44 |
45 | tests
46 | src
47 |
48 |
49 |
50 |
51 | maven-clean-plugin
52 | 3.1.0
53 |
54 |
55 |
56 | maven-resources-plugin
57 | 3.0.2
58 |
59 |
60 | maven-compiler-plugin
61 | 3.8.0
62 |
63 |
64 | maven-surefire-plugin
65 | 2.22.1
66 |
67 |
68 | maven-jar-plugin
69 | 3.0.2
70 |
71 |
72 | maven-install-plugin
73 | 2.5.2
74 |
75 |
76 | maven-deploy-plugin
77 | 2.8.2
78 |
79 |
80 |
81 | maven-site-plugin
82 | 3.7.1
83 |
84 |
85 | maven-project-info-reports-plugin
86 | 3.0.0
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/doc/outfmt.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | The output of ckjm is textual:
4 | one line for each class, each line contains 8 space-separated fields:
5 | the classname and the 7 metrics.
6 | If your application requires something more fancy,
7 | it is easy to post-process the ckjm output to
8 | obtain it.
9 | For example, the following sed script will generate
10 | XML output.
11 |
12 | #!/bin/sed -f
13 | 1i\
14 | \
15 |
16 | s/^//
17 | s/ /<\/classname>/
18 | s/ /<\/WMC>/
19 | s/ /<\/DIT>/
20 | s/ /<\/NOC>/
21 | s/ /<\/CBO>/
22 | s/ /<\/RFC>/
23 | s/ /<\/LCOM>/
24 | s/ /<\/Ca>/
25 | s/$/<\/NPM><\/metric>/
26 | $a\
27 |
28 |
29 | If you name the script ckjm2xml and make it executable,
30 | you can generate XML output and save it into a file as follows.
31 |
32 | java -jar /usr/local/lib/ckjm.jar *.class | ckjm2xml >metrics.xml
33 |
34 | (Replace the sequence /usr/local/lib/ckjm.jar
35 | with the actual path and filename of the ckjm version you are using.)
36 |
37 | Here is an example of the output.
38 |
41 |
42 |
43 |
44 | gr.spinellis.ckjm.ClassMetricsContainer310318022
45 | gr.spinellis.ckjm.MethodVisitor11102140018
46 | gr.spinellis.ckjm.CkjmOutputHandler11011031
47 | gr.spinellis.ckjm.ClassMetrics2410033196623
48 | gr.spinellis.ckjm.MetricsFilter7106301125
49 | gr.spinellis.ckjm.ClassVisitor131014713429
50 | gr.spinellis.ckjm.ClassMap310121002
51 | gr.spinellis.ckjm.PrintPlainResults21028012
52 |
53 |
54 |
55 | To copy the ckjm's output to the Microsoft Windows clipboard
56 | to later paste the results into an MS-Word table, simply
57 | pipe the output of ckjm to the winclip command of the
58 | Outwit tool suite.
59 |
60 | You can also plot the results in various formats by using
61 | gnuplot.
62 | Here is a diagram depicting the distribution of the CBO metric within
63 | the classes of Eclipse.
64 |
65 |
66 |
--------------------------------------------------------------------------------
/doc/metric.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | The metrics ckjm will calculate and display for
4 | each class are the following.
5 |
6 |
WMC - Weighted methods per class
7 | A class's weighted methods per class WMC
8 | metric is simply the sum of the complexities of its methods.
9 | As a measure of complexity we can use the cyclomatic complexity,
10 | or we can abritrarily assign a complexity value of 1 to each method.
11 | The ckjm program assigns a complexity value of 1 to each method,
12 | and therefore the value of the WMC is equal to the number of methods
13 | in the class.
14 |
DIT - Depth of Inheritance Tree
15 | The depth of inheritance tree (DIT) metric provides
16 | for each class a measure of the inheritance levels from the object
17 | hierarchy top.
18 | In Java where all classes inherit Object the minimum value
19 | of DIT is 1.
20 |
NOC - Number of Children
21 | A class's number of children (NOC)
22 | metric simply
23 | measures the number of immediate descendants of the class.
24 |
CBO - Coupling between object classes
25 | The coupling between object classes (CBO)
26 | metric represents the number of classes coupled to a given
27 | class (efferent couplings, Ce).
28 | This coupling can occur through method calls,
29 | field accesses, inheritance, arguments, return types,
30 | and exceptions.
31 |
RFC - Response for a Class
32 | The metric called the response for a class (RFC)
33 | measures the number of different
34 | methods that can be executed when an object of that
35 | class receives a message (when a method is invoked
36 | for that object).
37 | Ideally, we would want to find for each method
38 | of the class, the methods that class will call,
39 | and repeat this for each called method,
40 | calculating what is called the transitive closure
41 | of the method's call graph.
42 | This process can however be both expensive and quite
43 | inaccurate.
44 | In ckjm, we calculate a rough
45 | approximation to the response set
46 | by simply inspecting method calls within the class's
47 | method bodies.
48 | This simplification was also used in the 1994 Chidamber and Kemerer
49 | description of the metrics.
50 |
LCOM - Lack of cohesion in methods
51 | A class's lack of cohesion in methods (LCOM)
52 | metric counts the sets of methods in a class that are not related
53 | through the sharing of some of the class's fields.
54 | The original definition of this metric
55 | (which is the one used in ckjm)
56 | considers all pairs of a class's methods.
57 | In some of these pairs both methods access at
58 | least one common field of the class, while in
59 | other pairs the two methods to not share any
60 | common field accesses.
61 | The lack of cohesion in methods is then calculated
62 | by subtracting from the number of method pairs
63 | that don't share a field access the number of
64 | method pairs that do.
65 | Note that subsequent definitions
66 | of this metric used as a measurement basis the number
67 | of disjoint graph components of the class's methods.
68 | Others modified the definition of connectedness to
69 | include calls between the methods of the class.
70 | The program ckjm follows the original (1994) definition
71 | by Chidamber and Kemerer.
72 |
Ca - Afferent couplings
73 | A class's afferent couplings is a measure of how many other classes
74 | use the specific class.
75 | Ca is calculated using the same definition as that used for
76 | calculating CBO (Ce).
77 |
NPM - Number of Public Methods
78 | The NPM metric simply counts all the methods in a class that
79 | are declared as public.
80 | It can be used to measure the size of an API provided by a package.
81 |
21 | The ckjm program calculates the metrics from the code
22 | appearing in the compiled bytecode files.
23 | The Java compiler optimizes away some elements of the code
24 | (for example static final fields, and these do not
25 | take part in the calculations.
26 | You may want to consult the disassembled code
27 | (using a command like javap -c -private to see
28 | what elements ckjm takes into account.
29 |
30 |
40 | If you are getting messages like the one below, it means that ckjm
41 | can't locate the code for the corresponding classes, in order to properly
42 | calculate the depth of the inheritance tree (DIT) metric.
43 |
44 | java.lang.ClassNotFoundException: Exception while looking for class
45 | javax.servlet.http.HttpServlet: java.io.IOException:
46 | Couldn't find: javax.servlet.http.HttpServlet.class
47 |
48 | To solve this problem you must explicitly setup the
49 | java.ext.dirs property pointing to a directory containing
50 | the jar files where ckjm can locate those classes.
51 | Example:
52 |
53 | java -Djava.ext.dirs=lib -jar ckjm-1.8.jar *.class
54 |
55 |
67 | It's best to avoid putting spaces in file and directory names, because
68 | these can confuse many Unix-related tools that use spaces to separate
69 | arguments.
70 | If you can't avoid them, here are two tricks for getting around the problem.
71 | In a Windows environment use dir /x on the command line to
72 | obtain the short (8.3) name of the corresponding directory.
73 | On a Unix machine create a symbolic from the directory containing spaces
74 | to a directory without spaces, and use that second name:
75 |
76 | ln -s '/path/to/directory with spaces/' /tmp/shortname
77 |
78 |
79 |
--------------------------------------------------------------------------------
/contrib/ckjm_ruby-1.0/doc/classes/App.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | Class: App
9 |
10 |
11 |
12 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
171 | Computes the distribution of the 8 ckjm metrics by counting how many classes
173 | fall into a bucket with a specific metric value. Buckets are just
174 | individual metric values, (e.g. 1, 2, 3 for DIT). Returns the distribution
175 | as a hash of hashes:
176 |
Rajendra K. Bandi,
13 | Vijay K. Vaishnavi, and Daniel E. Turk.
14 | Predicting maintenance performance using object-oriented design complexity
15 | metrics.
16 | IEEE Transactions on Software Engineering, 29(1):77–87, 2003.
17 | (doi:10.1109/TSE.2003.1166590)
18 |
19 |
20 |
Victor R. Basili,
21 | Lionel C. Briand, and Walcélio L. Melo.
22 | A validation of object-oriented design metrics as quality indicators.
23 | IEEE Transactions on Software Engineering, 22(10):751–761,
24 | 1996.
25 | (doi:10.1109/32.544352)
26 |
27 |
28 |
Shyam R. Chidamber
29 | and Chris F. Kemerer.
30 | A metrics suite for object oriented design.
31 | IEEE Transactions on Software Engineering, 20(6):476–493, 1994.
32 | (doi:10.1109/32.295895)
33 |
34 |
35 |
Shyam R. Chidamber,
36 | David P. Darcy, and Chris F. Kemerer.
37 | Managerial use of metrics for object-oriented software: An exploratory
38 | analysis.
39 | IEEE Transactions on Software Engineering, 24(8):629–639, 1998.
40 | (doi:10.1109/32.707698)
41 |
42 |
43 |
Rudolf Ferenc, István
44 | Siket, and Tibor Gyimóthy.
45 | Extracting facts from
46 | open source software.
47 | In ICSM '04: Proceedings of the 20th IEEE International Conference on
48 | Software Maintenance (ICSM'04), pages 60–69. IEEE Computer Society,
49 | 2004.
50 |
51 |
53 |
Brian L.
54 | Henderson-Sellers, Larry L. Constantine, and Ian M. Graham.
55 | Coupling and cohesion: Towards a valid metrics suite for object-oriented
56 | analysis and design.
57 | Object Oriented Systems, 3(3):143–158, 1996.
58 |
59 |
60 |
Brian
61 | Henderson-Sellers.
62 | Object-Oriented Metrics: Measures of Complexity.
63 | Prentice-Hall, Englewood Cliffs, NJ, 1996.
64 |
65 |
66 |
Martin Hitz and
67 | Behzad Montazeri.
68 | Chidamber and Kemerer's metrics suite: A measurement theory perspective.
69 | IEEE Transactions on Software Engineering, 22(4):267–271, 1996.
70 | (doi:10.1109/32.491650)
71 |
72 |
73 |
Tobias Mayer and Tracy
74 | Hall.
75 | A critical analysis of current OO design metrics.
76 | Software Quality Control, 8(2):97–110, 1999.
77 | (doi:10.1023/A:1008900825849)
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/doc/bib.bib:
--------------------------------------------------------------------------------
1 | @article{MH99,
2 | author = {Tobias Mayer and Tracy Hall},
3 | title = {A Critical Analysis of Current {OO} Design Metrics},
4 | journal = {Software Quality Control},
5 | volume = {8},
6 | number = {2},
7 | year = {1999},
8 | issn = {0963-9314},
9 | pages = {97--110},
10 | doi = {http://dx.doi.org/10.1023/A:1008900825849},
11 | publisher = {Kluwer Academic Publishers},
12 | }
13 |
14 | @article{PV03,
15 | author = {Sandeep Purao and Vijay Vaishnavi},
16 | title = {Product metrics for object-oriented systems},
17 | journal = {ACM Computing Surveys},
18 | volume = {35},
19 | number = {2},
20 | year = {2003},
21 | issn = {0360-0300},
22 | pages = {191--221},
23 | doi = {http://doi.acm.org/10.1145/857076.857090},
24 | publisher = {ACM Press},
25 | Where="Have"
26 | }
27 |
28 |
29 | @article{BBM96,
30 | author = {Victor R. Basili and Lionel C. Briand and Walc\'{e}lio L. Melo},
31 | title = {A Validation of Object-Oriented Design Metrics as Quality Indicators},
32 | journal = ieeese,
33 | volume = {22},
34 | number = {10},
35 | year = {1996},
36 | issn = {0098-5589},
37 | pages = {751--761},
38 | doi = {http://dx.doi.org/10.1109/32.544352},
39 | publisher = {IEEE Press},
40 | }
41 |
42 | @article{CK94,
43 | author = {Shyam R. Chidamber and Chris F. Kemerer},
44 | title = {A Metrics Suite for Object Oriented Design},
45 | journal = ieeese,
46 | volume = {20},
47 | number = {6},
48 | year = {1994},
49 | issn = {0098-5589},
50 | pages = {476--493},
51 | doi = {http://dx.doi.org/10.1109/32.295895},
52 | publisher = {IEEE Press},
53 | Where="pub/lib"
54 | }
55 |
56 | @article{BVT03,
57 | author = {Rajendra K. Bandi and Vijay K. Vaishnavi and Daniel E. Turk},
58 | title = {Predicting Maintenance Performance Using Object-Oriented Design Complexity Metrics},
59 | journal = ieeese,
60 | volume = {29},
61 | number = {1},
62 | year = {2003},
63 | issn = {0098-5589},
64 | pages = {77--87},
65 | doi = {http://dx.doi.org/10.1109/TSE.2003.1166590},
66 | publisher = {IEEE Press},
67 | }
68 |
69 | @Book {Sel96,
70 | author="Brian Henderson-Sellers",
71 | Title="Object-Oriented Metrics: Measures of Complexity",
72 | Publisher="Prentice-Hall",
73 | Address="Englewood Cliffs, NJ",
74 | Year="1996"
75 | }
76 | @inproceedings{Ros98,
77 | author = {Linda H. Rosenberg},
78 | title = {Applying and Interpreting Object Oriented Metrics},
79 | booktitle = {Software Technology Conference '98},
80 | year = {1998},
81 | location = "Salt Lake City, Utah",
82 | Where="pub/lib,photocopy",
83 | URL="http://www.literateprogramming.com/ooapply.pdf"
84 | }
85 |
86 | @article{HCG96,
87 | author = {Henderson-Sellers, Brian L. and Constantine, Larry L. and Graham, Ian M.},
88 | title = {Coupling and Cohesion: Towards a Valid Metrics Suite for Object-oriented Analysis and Design},
89 | journal = {Object Oriented Systems},
90 | volume = {3},
91 | number = {3},
92 | year = {1996},
93 | pages = {143--158}
94 | }
95 |
96 | @article{HM96,
97 | author = {Martin Hitz and Behzad Montazeri},
98 | title = {{C}hidamber and {K}emerer's Metrics Suite: A Measurement Theory Perspective},
99 | journal = ieeese,
100 | volume = {22},
101 | number = {4},
102 | year = {1996},
103 | issn = {0098-5589},
104 | pages = {267--271},
105 | doi = {http://dx.doi.org/10.1109/32.491650},
106 | publisher = {IEEE Press},
107 | Where="pub/lib"
108 | }
109 |
110 | @article{CDK98,
111 | author = {Shyam R. Chidamber and David P. Darcy and Chris F. Kemerer},
112 | title = {Managerial Use of Metrics for Object-Oriented Software: An Exploratory Analysis},
113 | journal = ieeese,
114 | volume = {24},
115 | number = {8},
116 | year = {1998},
117 | issn = {0098-5589},
118 | pages = {629--639},
119 | doi = {http://dx.doi.org/10.1109/32.707698},
120 | publisher = {IEEE Press},
121 | Where="pub/lib"
122 | }
123 |
124 | % Link from http://sel.gsfc.nasa.gov/website/sew/past-sew.htm
125 | @inproceedings{RSG99,
126 | author = {Linda Rosenberg and Ruth Stapko and Al Gallo},
127 | title = {Risk-based Object Oriented Testing},
128 | booktitle = {Twenty-Fourth Annual Software Engineering Workshop},
129 | year = {1999},
130 | month=dec,
131 | location = {Goddard Space Flight Center, Greenbelt, MD},
132 | Organization="NASA, Software Engineering Laboratory",
133 | Where="pub/lib",
134 | URL="http://sel.gsfc.nasa.gov/website/sew/1999/topics/rosenberg_SEW99paper.pdf"
135 | }
136 |
137 |
138 | @inproceedings{RSG99b,
139 | author = {Linda Rosenberg and Ruth Stapko and Al Gallo},
140 | title = {Applying Object-Oriented Metrics},
141 | booktitle = {Sixth International Symposium on Software Metrics---Measurement for Object-Oriented Software Projects Workshop},
142 | year = {1999},
143 | Note="Presentation available online \url{http://www.software.org/metrics99/rosenberg.ppt} (December 2005)",
144 | month=nov,
145 | location = {Boca Raton, FL},
146 | Where="pub/lib",
147 | URL="http://www.software.org/metrics99/rosenberg.ppt"
148 | }
149 |
150 | @inproceedings{FSG04,
151 | author = {Rudolf Ferenc and Istv\'{a}n Siket and Tibor Gyim\'{o}thy},
152 | title = {Extracting Facts from Open Source Software},
153 | booktitle = {ICSM '04: Proceedings of the 20th IEEE International Conference on Software Maintenance (ICSM'04)},
154 | year = {2004},
155 | isbn = {0-7695-2213-0},
156 | pages = {60--69},
157 | publisher = {IEEE Computer Society},
158 | Where="pub/lib,have"
159 | }
160 |
161 | @Article{Spi05g,
162 | Title="Tool Writing: A Forgotten Art?",
163 | Author="Diomidis Spinellis",
164 | Journal="IEEE Software",
165 | Month="July/August",
166 | Pages="9--11",
167 | Volume=22,
168 | Number=4,
169 | Year=2005,
170 | DOI="doi:10.1109/MS.2005.111",
171 | URL="http://www.dmst.aueb.gr/dds/pubs/jrnl/2005-IEEESW-TotT/html/v22n4.html"
172 | }
173 |
174 | @Book {Spi06,
175 | Author="Diomidis Spinellis",
176 | Title="Code Quality: The Open Source Perspective",
177 | Publisher="Addison-Wesley",
178 | Address="Boston, MA",
179 | URL="http://www.spinellis.gr/codequality",
180 | XISBN="0-321-16607-8",
181 | Year=2006
182 | }
183 |
184 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 | ckjm — Chidamber and Kemerer Java Metrics
10 |
11 |
12 |
13 |
14 |
ckjm dds
15 |
ckjm — Chidamber and Kemerer Java Metrics
16 |
17 |
18 |
19 | The program ckjm calculates Chidamber and Kemerer object-oriented
20 | metrics by processing the bytecode of compiled Java files.
21 | The program calculates for each class the following six metrics proposed
22 | by Chidamber and Kemerer.
23 |
24 |
25 |
WMC: Weighted methods per class
26 |
DIT: Depth of Inheritance Tree
27 |
NOC: Number of Children
28 |
CBO: Coupling between object classes
29 |
RFC: Response for a Class
30 |
LCOM: Lack of cohesion in methods
31 |
32 |
33 | In addition it also calculates for each class
34 |
35 |
36 |
Ca: Afferent couplings
37 |
NPM: Number of public methods
38 |
39 |
Citation and Background
40 |
41 | If you use this tool in your research, please cite it as follows.
42 | Diomidis Spinellis.
43 | Tool writing: A forgotten art?
44 | IEEE Software, 22(4):9–11, July/August 2005.
45 | (doi:10.1109/MS.2005.111).
46 |
47 |
48 | I wrote this program out of frustration over the
49 | lack
50 | of reliable programs to calculate the
51 | Chidamber and Kemerer object-oriented metrics I needed
52 | to illustrate some concepts in my book
53 | Code Quality: The Open Source Perspective.
54 | The programs I found on the web were either
55 | incomplete (they calculated only some of the metrics),
56 | or unreliable (they calculated results that were obviously wrong),
57 | or extremely inefficient (they required GB of RAM and hours of processing).
58 | Ckjm is mean and lean, following the Unix tradition of doing
59 | one thing well.
60 | It will not automatically recurse directories looking for the files
61 | you want measured and it does not offer a GUI.
62 | However, it does this job thoroughly, and efficiently:
63 | on a 1.6GHz Pentium-M machine it will process the 33MB of the Eclipse 3.0
64 | jar files (19717 classes) in 95 seconds.
65 |
66 |
Getting Started
67 |
68 | To run the program you simply specify the class files
69 | (or pairs of jar/class files)
70 | on its command line or standard input.
71 | The program will produce on its standard output a line for each class
72 | containing the complete name of the class and the values of its metrics.
73 | This operation model allows the tool to be easilly extended using textual
74 | pre- and post-processors.
75 |
76 |
77 | From version 1.2 and onward ckjm can be used as an
78 | ant task, and can also directly generate XML output.
79 | You can post-process the XML output with XSLT to generate nice-looking
80 | reports.
81 | Here is a report example using
82 | simple report style
83 | and here is an example using the
84 | fancy report style.
85 | XSL files for both report styles are part of the distribution.
86 |
87 |
88 |
89 |
90 |
Download and Links
91 | Ckjm is hereby made freely available as Open Source Software.
92 | The current version of ckjm is VERSION.
93 | You can download ckjm and its documentation from the following links:
94 |
95 |
ckjm package - .tar.gz
96 | (compressed tar file containing the source code, the compiled jar file,
97 | and the complete documentation in HTML format).
98 |
99 |
GitHub page
100 | (use it to obtain the latest version,
101 | track progress,
102 | report issues,
103 | and contribute improvements).
104 |
105 |
ckjm package - .zip
106 | (zip file containing the source code, the compiled doclet,
107 | and the complete documentation in HTML format).
108 |
109 |
User documentation
110 | (table of contents - suitable for web browsing).
111 |
145 |
146 | (C) Copyright 2005-2010 D. Spinellis.
147 | May be freely uploaded by WWW viewers and similar programs.
148 | All other rights reserved.
149 |
150 | Last modified: $Date: 2010/05/22 10:27:16 $
151 |
152 |
153 |
154 |
155 |
156 |
--------------------------------------------------------------------------------
/contrib/ckjm_ruby-1.0/mk_ckjm_graphs.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Copyright (c) 2007, Edwin Fine, Fine Computer Consultants, Inc.
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are
7 | # met:
8 | #
9 | # * Redistributions of source code must retain the above copyright
10 | # notice, this list of conditions and the following disclaimer.
11 | # * Redistributions in binary form must reproduce the above copyright
12 | # notice, this list of conditions and the following disclaimer in the
13 | # documentation and/or other materials provided with the distribution.
14 | # * Neither the name of Diomidis Spinellis nor the names of its
15 | # contributors may be used to endorse or promote products derived from
16 | # this software without specific prior written permission.
17 | #
18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 | # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | #++
30 | # This program gets statistics based on the output of the ckjm program
31 | # (http://www.spinellis.gr/sw/ckjm) and generates graphs in PNG format
32 | # using gnuplot (V4 or later required). There is one graph per metric,
33 | # which all get stored in the current directory. ckjm must create output
34 | # using the "plain" (default) option.
35 | #
36 | # To run this program:
37 | #
38 | # ruby mk_ckjm_graphs.rb ckjm-text-file
39 | #
40 | # ckjm plain output creates a text file with a line for each
41 | # class. Each line consists of the class name, followed by 8
42 | # numeric metrics as described below. Values are space-separated.
43 | #
44 | # com.my.ClassName WMC DIT NOC CBO RFC LCOM Ca NPM
45 | #
46 | # Example:
47 | #
48 | # com.vz.schedule.data.ScheduleData 15 1 0 0 20 69 3 15
49 | #
50 | # The following text is from Diomidis Spinellis' ckjm web page:
51 | #
52 | # The metrics ckjm will calculate and display for each class are the
53 | # following.
54 | #
55 | # * WMC - Weighted methods per class.
56 | # A class's weighted methods per class WMC metric is simply the sum
57 | # of the complexities of its methods. As a measure of complexity we
58 | # can use the cyclomatic complexity, or we can abritrarily assign a
59 | # complexity value of 1 to each method. The ckjm program assigns a
60 | # complexity value of 1 to each method, and therefore the value of
61 | # the WMC is equal to the number of methods in the class.
62 | # * DIT - Depth of Inheritance Tree.
63 | # The depth of inheritance tree (DIT) metric provides for each class a
64 | # measure of the inheritance levels from the object hierarchy top. In
65 | # Java where all classes inherit Object the minimum value of DIT is 1.
66 | # * NOC - Number of Children.
67 | # A class's number of children (NOC) metric simply measures the number
68 | # of immediate descendants of the class.
69 | # * CBO - Coupling between object classes.
70 | # The coupling between object classes (CBO) metric represents the
71 | # number of classes coupled to a given class (efferent couplings,
72 | # Ce). This coupling can occur through method calls, field accesses,
73 | # inheritance, arguments, return types, and exceptions.
74 | # * RFC - Response for a Class.
75 | # The metric called the response for a class (RFC) measures the
76 | # number of different methods that can be executed when an object of
77 | # that class receives a message (when a method is invoked for that
78 | # object). Ideally, we would want to find for each method of the class,
79 | # the methods that class will call, and repeat this for each called
80 | # method, calculating what is called the transitive closure of the
81 | # method's call graph. This process can however be both expensive
82 | # and quite inaccurate. In ckjm, we calculate a rough approximation
83 | # to the response set by simply inspecting method calls within the
84 | # class's method bodies. This simplification was also used in the 1994
85 | # Chidamber and Kemerer description of the metrics.
86 | # * LCOM - Lack of cohesion in methods.
87 | # A class's lack of cohesion in methods (LCOM) metric counts the sets
88 | # of methods in a class that are not related through the sharing of
89 | # some of the class's fields. The original definition of this metric
90 | # (which is the one used in ckjm) considers all pairs of a class's
91 | # methods. In some of these pairs both methods access at least one
92 | # common field of the class, while in other pairs the two methods
93 | # to not share any common field accesses. The lack of cohesion in
94 | # methods is then calculated by subtracting from the number of method
95 | # pairs that don't share a field access the number of method pairs
96 | # that do. Note that subsequent definitions of this metric used as a
97 | # measurement basis the number of disjoint graph components of the
98 | # class's methods. Others modified the definition of connectedness
99 | # to include calls between the methods of the class. The program ckjm
100 | # follows the original (1994) definition by Chidamber and Kemerer.
101 | # * Ca - Afferent couplings.
102 | # A class's afferent couplings is a measure of how many other classes
103 | # use the specific class. Ca is calculated using the same definition
104 | # as that used for calculating CBO (Ce).
105 | # * NPM - Number of Public Methods.
106 | # The NPM metric simply counts all the methods in a class that are
107 | # declared as public. It can be used to measure the size of an API
108 | # provided by a package.
109 |
110 | require 'metrics_utils'
111 |
112 | # This is the top-level application that ties together
113 | # all the other elements to plot the ckjm data.
114 | class App
115 | # Runs the application.
116 | # +argv+:: array containing [ckjm_file_name, project_desc].
117 | def App.run(argv)
118 | App.usage unless argv.length == 2
119 | ckjm_file_name, project_desc = argv
120 | jm = MetricsUtils::JavaMetrics.new(ckjm_file_name)
121 | plotter = MetricsUtils::Plotter.instance
122 | grapher = MetricsUtils::CKJMMetricGrapher.new(ckjm_file_name, project_desc, plotter, jm)
123 | grapher.plot_metrics
124 | end
125 |
126 | private
127 |
128 | # Displays a usage message and exits.
129 | def App.usage
130 | puts "usage: ruby #{File.basename $0} ckjm-input-file project-desc"
131 | exit 1
132 | end
133 | end
134 |
135 | argv = ARGV.to_a
136 | $debug_mode = argv.reject! {|elem| elem == "-d"}
137 | App.run(argv)
138 |
--------------------------------------------------------------------------------
/contrib/ckjm_ruby-1.0/doc/classes/MetricsUtils/Plotter.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 | Class: MetricsUtils::Plotter
9 |
10 |
11 |
12 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
83 | This class exists to provide access to the underlying plotting mechanism.
84 | It configures the plotter program and accepts plot data to send to the
85 | program. At the moment, it uses gnuplot as the plotter program. It seems
86 | unlikely to change in the foreseeable future unless I make a full plotter
87 | abstraction, which given the time I have to do this, is about as likely as
88 | me winning the jackpot.
89 |
200 | Opens the plotter for writing. If a block is provided, calls that block and
201 | closes the plotter when the block returns. Always returns nil.
202 |
73 | This program gets statistics based on the output of the ckjm program (www.spinellis.gr/sw/ckjm) and
75 | generates graphs in PNG format using gnuplot (V4 or later required). There
76 | is one graph per metric, which all get stored in the current directory.
77 | ckjm must create output using the "plain" (default) option.
78 |
79 |
80 | To run this program:
81 |
82 |
83 | ruby mk_ckjm_graphs.rb ckjm-text-file
84 |
85 |
86 | ckjm plain output creates a text file with a line for each class. Each line
87 | consists of the class name, followed by 8 numeric metrics as described
88 | below. Values are space-separated.
89 |
90 |
91 | com.my.ClassName WMC DIT NOC CBO RFC LCOM Ca NPM
92 |
100 | The following text is from Diomidis Spinellis’ ckjm web page:
101 |
102 |
103 | The metrics ckjm will calculate and display for each class are the
104 | following.
105 |
106 |
107 |
WMC - Weighted methods per class. A class‘s weighted methods
108 | per class WMC metric is simply the sum of the complexities of its methods.
109 | As a measure of complexity we can use the cyclomatic complexity, or we can
110 | abritrarily assign a complexity value of 1 to each method. The ckjm program
111 | assigns a complexity value of 1 to each method, and therefore the value of
112 | the WMC is equal to the number of methods in the class.
113 |
114 |
115 |
DIT - Depth of Inheritance Tree. The depth of inheritance tree (DIT)
116 | metric provides for each class a measure of the inheritance levels from the
117 | object hierarchy top. In Java where all classes inherit Object the minimum
118 | value of DIT is 1.
119 |
120 |
121 |
NOC - Number of Children. A class‘s number of children (NOC)
122 | metric simply measures the number of immediate descendants of the class.
123 |
124 |
125 |
CBO - Coupling between object classes. The coupling between object
126 | classes (CBO) metric represents the number of classes coupled to a given
127 | class (efferent couplings, Ce). This coupling can occur through method
128 | calls, field accesses, inheritance, arguments, return types, and
129 | exceptions.
130 |
131 |
132 |
RFC - Response for a Class. The metric called the response for a
133 | class (RFC) measures the number of different methods that can be executed
134 | when an object of that class receives a message (when a method is invoked
135 | for that object). Ideally, we would want to find for each method of the
136 | class, the methods that class will call, and repeat this for each called
137 | method, calculating what is called the transitive closure of the
138 | method‘s call graph. This process can however be both expensive and
139 | quite inaccurate. In ckjm, we calculate a rough approximation to the
140 | response set by simply inspecting method calls within the class‘s
141 | method bodies. This simplification was also used in the 1994 Chidamber and
142 | Kemerer description of the metrics.
143 |
144 |
145 |
LCOM - Lack of cohesion in methods. A class‘s lack of cohesion
146 | in methods (LCOM) metric counts the sets of methods in a class that are not
147 | related through the sharing of some of the class‘s fields. The
148 | original definition of this metric (which is the one used in ckjm)
149 | considers all pairs of a class‘s methods. In some of these pairs both
150 | methods access at least one common field of the class, while in other pairs
151 | the two methods to not share any common field accesses. The lack of
152 | cohesion in methods is then calculated by subtracting from the number of
153 | method pairs that don‘t share a field access the number of method
154 | pairs that do. Note that subsequent definitions of this metric used as a
155 | measurement basis the number of disjoint graph components of the
156 | class‘s methods. Others modified the definition of connectedness to
157 | include calls between the methods of the class. The program ckjm follows
158 | the original (1994) definition by Chidamber and Kemerer.
159 |
160 |
161 |
Ca - Afferent couplings. A class‘s afferent couplings is a
162 | measure of how many other classes use the specific class. Ca is calculated
163 | using the same definition as that used for calculating CBO (Ce).
164 |
165 |
166 |
NPM - Number of Public Methods. The NPM metric simply counts all the
167 | methods in a class that are declared as public. It can be used to measure
168 | the size of an API provided by a package.
169 |
170 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/src/gr/spinellis/ckjm/ClassVisitor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * (C) Copyright 2005 Diomidis Spinellis
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package gr.spinellis.ckjm;
18 |
19 | import org.apache.bcel.classfile.*;
20 | import org.apache.bcel.generic.*;
21 | import org.apache.bcel.Repository;
22 | import org.apache.bcel.Constants;
23 | import org.apache.bcel.util.*;
24 | import java.io.*;
25 | import java.util.*;
26 | import java.lang.reflect.Modifier;
27 |
28 | /**
29 | * Visit a class updating its Chidamber-Kemerer metrics.
30 | *
31 | * @see ClassMetrics
32 | * @version $Revision: 1.21 $
33 | * @author Diomidis Spinellis
34 | */
35 | public class ClassVisitor extends org.apache.bcel.classfile.EmptyVisitor {
36 | /** The class being visited. */
37 | private JavaClass visitedClass;
38 | /** The class's constant pool. */
39 | private ConstantPoolGen cp;
40 | /** The class's fully qualified name. */
41 | private String myClassName;
42 | /** The container where metrics for all classes are stored. */
43 | private ClassMetricsContainer cmap;
44 | /** The emtrics for the class being visited. */
45 | private ClassMetrics cm;
46 | /* Classes encountered.
47 | * Its cardinality is used for calculating the CBO.
48 | */
49 | private HashSet efferentCoupledClasses = new HashSet();
50 | /** Methods encountered.
51 | * Its cardinality is used for calculating the RFC.
52 | */
53 | private HashSet responseSet = new HashSet();
54 | /** Use of fields in methods.
55 | * Its contents are used for calculating the LCOM.
56 | * We use a Tree rather than a Hash to calculate the
57 | * intersection in O(n) instead of O(n*n).
58 | */
59 | ArrayList> mi = new ArrayList>();
60 |
61 | public ClassVisitor(JavaClass jc, ClassMetricsContainer classMap) {
62 | visitedClass = jc;
63 | cp = new ConstantPoolGen(visitedClass.getConstantPool());
64 | cmap = classMap;
65 | myClassName = jc.getClassName();
66 | cm = cmap.getMetrics(myClassName);
67 | }
68 |
69 | /** Return the class's metrics container. */
70 | public ClassMetrics getMetrics() { return cm; }
71 |
72 | public void start() {
73 | visitJavaClass(visitedClass);
74 | }
75 |
76 | /** Calculate the class's metrics based on its elements. */
77 | public void visitJavaClass(JavaClass jc) {
78 | String super_name = jc.getSuperclassName();
79 | String package_name = jc.getPackageName();
80 |
81 | cm.setVisited();
82 | if (jc.isPublic())
83 | cm.setPublic();
84 | ClassMetrics pm = cmap.getMetrics(super_name);
85 |
86 | pm.incNoc();
87 | try {
88 | cm.setDit(jc.getSuperClasses().length);
89 | } catch( ClassNotFoundException ex) {
90 | System.err.println("Error obtaining all superclasses of " + jc);
91 | }
92 | registerCoupling(super_name);
93 |
94 | String ifs[] = jc.getInterfaceNames();
95 | /* Measuring decision: couple interfaces */
96 | for (int i = 0; i < ifs.length; i++)
97 | registerCoupling(ifs[i]);
98 |
99 | Field[] fields = jc.getFields();
100 | for(int i=0; i < fields.length; i++)
101 | fields[i].accept(this);
102 |
103 | Method[] methods = jc.getMethods();
104 | for(int i=0; i < methods.length; i++)
105 | methods[i].accept(this);
106 | }
107 |
108 | /** Add a given class to the classes we are coupled to */
109 | public void registerCoupling(String className) {
110 | /* Measuring decision: don't couple to Java SDK */
111 | if ((MetricsFilter.isJdkIncluded() ||
112 | !ClassMetrics.isJdkClass(className)) &&
113 | !myClassName.equals(className)) {
114 | efferentCoupledClasses.add(className);
115 | cmap.getMetrics(className).addAfferentCoupling(myClassName);
116 | }
117 | }
118 |
119 | /* Add the type's class to the classes we are coupled to */
120 | public void registerCoupling(Type t) {
121 | registerCoupling(className(t));
122 | }
123 |
124 | /* Add a given class to the classes we are coupled to */
125 | void registerFieldAccess(String className, String fieldName) {
126 | registerCoupling(className);
127 | if (className.equals(myClassName))
128 | mi.get(mi.size() - 1).add(fieldName);
129 | }
130 |
131 | /* Add a given method to our response set */
132 | void registerMethodInvocation(String className, String methodName, Type[] args) {
133 | registerCoupling(className);
134 | /* Measuring decision: calls to JDK methods are included in the RFC calculation */
135 | incRFC(className, methodName, args);
136 | }
137 |
138 | /** Called when a field access is encountered. */
139 | public void visitField(Field field) {
140 | registerCoupling(field.getType());
141 | }
142 |
143 | /** Called when encountering a method that should be included in the
144 | class's RFC. */
145 | private void incRFC(String className, String methodName, Type[] arguments) {
146 | String argumentList = Arrays.asList(arguments).toString();
147 | // remove [ ] chars from begin and end
148 | String args = argumentList.substring(1, argumentList.length() - 1);
149 | String signature = className + "." + methodName + "(" + args + ")";
150 | responseSet.add(signature);
151 | }
152 |
153 | /** Called when a method invocation is encountered. */
154 | public void visitMethod(Method method) {
155 | MethodGen mg = new MethodGen(method, visitedClass.getClassName(), cp);
156 |
157 | Type result_type = mg.getReturnType();
158 | Type[] argTypes = mg.getArgumentTypes();
159 |
160 | registerCoupling(mg.getReturnType());
161 | for (int i = 0; i < argTypes.length; i++)
162 | registerCoupling(argTypes[i]);
163 |
164 | String[] exceptions = mg.getExceptions();
165 | for (int i = 0; i < exceptions.length; i++)
166 | registerCoupling(exceptions[i]);
167 |
168 | /* Measuring decision: A class's own methods contribute to its RFC */
169 | incRFC(myClassName, method.getName(), argTypes);
170 |
171 | cm.incWmc();
172 | if (Modifier.isPublic(method.getModifiers()))
173 | cm.incNpm();
174 | mi.add(new TreeSet());
175 | MethodVisitor factory = new MethodVisitor(mg, this);
176 | factory.start();
177 | }
178 |
179 | /** Return a class name associated with a type. */
180 | static String className(Type t) {
181 | String ts = t.toString();
182 |
183 | if (t.getType() <= Constants.T_VOID) {
184 | return "java.PRIMITIVE";
185 | } else if(t instanceof ArrayType) {
186 | ArrayType at = (ArrayType)t;
187 | return className(at.getBasicType());
188 | } else {
189 | return t.toString();
190 | }
191 | }
192 |
193 | /** Do final accounting at the end of the visit. */
194 | public void end() {
195 | cm.setCbo(efferentCoupledClasses.size());
196 | cm.setRfc(responseSet.size());
197 | /*
198 | * Calculate LCOM as |P| - |Q| if |P| - |Q| > 0 or 0 otherwise
199 | * where
200 | * P = set of all empty set intersections
201 | * Q = set of all nonempty set intersections
202 | */
203 | int lcom = 0;
204 | for (int i = 0; i < mi.size(); i++)
205 | for (int j = i + 1; j < mi.size(); j++) {
206 | /* A shallow unknown-type copy is enough */
207 | TreeSet> intersection = (TreeSet>)mi.get(i).clone();
208 | intersection.retainAll(mi.get(j));
209 | if (intersection.size() == 0)
210 | lcom++;
211 | else
212 | lcom--;
213 | }
214 | cm.setLcom(lcom > 0 ? lcom : 0);
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/contrib/ckjm_ruby-1.0/metrics_utils.rb:
--------------------------------------------------------------------------------
1 | #--
2 | # Copyright (c) 2007, Edwin Fine, Fine Computer Consultants, Inc.
3 | # All rights reserved.
4 | #
5 | # Redistribution and use in source and binary forms, with or without
6 | # modification, are permitted provided that the following conditions are
7 | # met:
8 | #
9 | # * Redistributions of source code must retain the above copyright
10 | # notice, this list of conditions and the following disclaimer.
11 | # * Redistributions in binary form must reproduce the above copyright
12 | # notice, this list of conditions and the following disclaimer in the
13 | # documentation and/or other materials provided with the distribution.
14 | # * Neither the name of Diomidis Spinellis nor the names of its
15 | # contributors may be used to endorse or promote products derived from
16 | # this software without specific prior written permission.
17 | #
18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 | # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 | # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 | # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | #++
30 | # This module contains utilities to plot Chidamber-Kemerer metrics.
31 | module MetricsUtils
32 |
33 | require 'singleton'
34 |
35 | # This class exists to provide access to the underlying plotting mechanism.
36 | # It configures the plotter program and accepts plot data to send to the program.
37 | # At the moment, it uses gnuplot as the plotter program. It seems unlikely to
38 | # change in the foreseeable future unless I make a full plotter abstraction,
39 | # which given the time I have to do this, is about as likely as me winning
40 | # the jackpot.
41 | class Plotter
42 | include Singleton
43 |
44 | # Initializes the plotter instance
45 | def initialize
46 | @plot_cmd = "gnuplot -"
47 | @plot_cmd << " > /dev/null 2>&1" unless $debug_mode
48 | end
49 |
50 | # Opens the plotter for writing. If a block is provided,
51 | # calls that block and closes the plotter when the block
52 | # returns. Always returns +nil+.
53 | def open(&blk) # :yields:
54 | @plot_pipe = IO.popen(@plot_cmd, "w")
55 |
56 | if blk
57 | begin
58 | blk.call
59 | ensure
60 | self.close
61 | end
62 | end
63 | nil
64 | end
65 |
66 | # Closes the plotter if it's open.
67 | # Returns nil.
68 | def close
69 | @plot_pipe && @plot_pipe.close
70 | ensure
71 | @plot_pipe = nil
72 | end
73 |
74 | # Prints plot data to the plotter.
75 | def print_to_graph(plot_data)
76 | @plot_pipe.puts plot_data
77 | puts(plot_data) if $debug_mode
78 | end
79 |
80 | # Sends an "end of data" signal to the plotter
81 | # to signify the closing of a plot.
82 | def end_of_data
83 | print_to_graph "e" # gnuplot-specific
84 | end
85 |
86 | end # class Plotter
87 |
88 | # This class parses the text output of the ckjm program
89 | # and stores the data points.
90 | class JavaMetrics
91 | # :stopdoc:
92 | # Metrics are expected in this order in the input record
93 | METRICS = [
94 | [ :wmc, 'Weighted methods per class' ],
95 | [ :dit, 'Depth of Inheritance Tree' ],
96 | [ :noc, 'Number of Children' ],
97 | [ :cbo, 'Coupling between object classes' ],
98 | [ :rfc, 'Response for a Class' ],
99 | [ :lcom, 'Lack of cohesion in methods' ],
100 | [ :ca, 'Afferent couplings' ],
101 | [ :npm, 'Number of Public Methods' ]
102 | ].freeze # :nodoc:
103 |
104 | # Maps metric symbols to long descriptions
105 | METRIC_DESC = Hash[*METRICS.flatten].freeze
106 | # :startdoc:
107 |
108 | # Initializes this instance with the name of the
109 | # text file containing the output of the ckjm
110 | # program.
111 | def initialize(ckjm_file_name)
112 | @ckjm_file_name = ckjm_file_name
113 | @distribution = {}
114 | end
115 |
116 | # Computes the distribution of the 8 ckjm metrics
117 | # by counting how many classes fall into a bucket
118 | # with a specific metric value. Buckets are just
119 | # individual metric values, (e.g. 1, 2, 3 for DIT).
120 | # Returns the distribution as a hash of hashes:
121 | # { metric_sym => { metric_value => count } }
122 | # Example:
123 | # { :wmc => { 7 => 134 } }
124 | def metrics
125 | @distribution.clear
126 | File.foreach(@ckjm_file_name) do |line|
127 | line.chomp!
128 | if line =~ /^\S+(\s+\d+){8}\s*$/
129 | class_name, *metrics_vals = line.split(/\s+/)
130 | METRICS.each_index do |i|
131 | value = metrics_vals[i].to_i
132 | (@distribution[METRICS[i][0]] ||= Hash.new(0))[value] += 1
133 | end
134 | end
135 | end
136 | @distribution
137 | end
138 |
139 | # Returns string description corresponding
140 | # to +sym+; raises +ArgumentError+ if +sym+ unknown.
141 | # Valid values for +sym+ are :wmc, :dit, :noc,
142 | # :cbo, :rfc, :lcom, :ca, and :npm.
143 | def metric_desc(sym)
144 | METRIC_DESC[sym] or raise ArgumentError, "Unknown symbol :#{sym}"
145 | end
146 | end
147 |
148 | # This class graphs the Chidamber-Kemerer metrics to PNG
149 | # files, as currently configured. It needs gnuplot v4.0 or later.
150 | class CKJMMetricGrapher
151 | FILE_FORMAT = "png"
152 | FORMAT_OPTIONS = "small"
153 |
154 | # Initializes the instance.
155 | # +ckjm_file_name+:: Input file
156 | # +project_desc+:: Short project description to go on graphs
157 | # +plotter+:: A Plotter-like object that responds to open, close,
158 | # print_to_graph(str), and end_of_data
159 | # +jm+:: An instance of the JavaMetrics object
160 | def initialize(ckjm_file_name, project_desc, plotter, jm)
161 | @ckjm_file_name, @project_desc, @plotter, @jm = ckjm_file_name, project_desc, plotter, jm
162 | end
163 |
164 | # Plots all metrics
165 | def plot_metrics
166 | @jm.metrics.each do |metric_sym, vals|
167 | @plotter.open do
168 | plot_metric metric_sym, vals
169 | end
170 | end
171 | end
172 |
173 | private
174 |
175 | # Returns file name for graph
176 | def fmt_graph_filename(metric_sym)
177 | "#{@project_desc.gsub(/\s+/, '_')}_#{metric_sym.to_s}_metric.png"
178 | end
179 |
180 | # Returns graph title
181 | def fmt_graph_title(metric_sym)
182 | "#{@jm.metric_desc(metric_sym)} (#{metric_sym.to_s.upcase})"
183 | end
184 |
185 | # Plots a single metric whose symbol is *sym* (e.g. :dit)
186 | # and which consists of the hash *vals*. Each hash key/value
187 | # pair is { metric_value => count }.
188 | def plot_metric(metric_sym, vals)
189 | @plotter.print_to_graph %{
190 | set terminal #{FILE_FORMAT} #{FORMAT_OPTIONS}
191 | set output '#{fmt_graph_filename(metric_sym)}'
192 | set title '#{fmt_graph_title(metric_sym)}'
193 | set xrange [-0.5:*]
194 | set xlabel '#{metric_sym.to_s.upcase}'
195 | set ylabel 'Number of classes'
196 | set timestamp 'Generated for #@project_desc on %Y/%m/%d' top
197 | set boxwidth 0.8 absolute
198 | set style fill solid 0.25 border
199 | show timestamp
200 | plot '-' using 1:2 notitle with boxes
201 | }
202 |
203 | vals.sort.each do |point|
204 | @plotter.print_to_graph point.join(" ")
205 | end
206 |
207 | @plotter.end_of_data
208 | @plotter.print_to_graph "set output" # close file, end of plot
209 | end
210 |
211 | end
212 | end
213 |
--------------------------------------------------------------------------------
/xsl/ckjm_extra.xsl:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | CKJM Chidamber and Kemerer Java Metrics
30 |
31 |
86 |
87 |
88 |
137 | A class's weighted methods per class WMC
138 | metric is simply the sum of the complexities of its methods.
139 | As a measure of complexity we can use the cyclomatic complexity,
140 | or we can abritrarily assign a complexity value of 1 to each method.
141 | The ckjm program assigns a complexity value of 1 to each method,
142 | and therefore the value of the WMC is equal to the number of methods
143 | in the class.
144 |
DIT - Depth of Inheritance Tree
145 | The depth of inheritance tree (DIT) metric provides
146 | for each class a measure of the inheritance levels from the object
147 | hierarchy top.
148 | In Java where all classes inherit Object the minimum value
149 | of DIT is 1.
150 |
NOC - Number of Children
151 |
152 | A class's number of children (NOC)
153 | metric simply
154 | measures the number of immediate descendants of the class.
155 |
CBO - Coupling between object classes
156 | The coupling between object classes (CBO)
157 | metric represents the number of classes coupled to a given
158 | class.
159 | This coupling can occur through method calls,
160 | field accesses, inheritance, arguments, return types,
161 | and exceptions.
162 |
RFC - Response for a Class
163 | The metric called the response for a class (RFC)
164 | measures the number of different
165 | methods that can be executed when an object of that
166 | class receives a message (when a method is invoked
167 | for that object).
168 | Ideally, we would want to find for each method
169 | of the class, the methods that class will call,
170 | and repeat this for each called method,
171 | calculating what is called the transitive closure
172 |
173 | of the method's call graph.
174 | This process can however be both expensive and quite
175 | inaccurate.
176 | In ckjm, we calculate a rough
177 | approximation to the response set
178 | by simply inspecting method calls within the class's
179 | method bodies.
180 | This simplification was also used in the 1994 Chidamber and Kemerer
181 | description of the metrics.
182 |
LCOM - Lack of cohesion in methods
183 | A class's lack of cohesion in methods (LCOM)
184 | metric counts the sets of methods in a class that are not related
185 | through the sharing of some of the class's fields.
186 | The original definition of this metric
187 | (which is the one used in ckjm)
188 | considers all pairs of a class's methods.
189 | In some of these pairs both methods access at
190 | least one common field of the class, while in
191 | other pairs the two methods to not share any
192 | common field accesses.
193 | The lack of cohesion in methods is then calculated
194 | by subtracting from the number of method pairs
195 | that don't share a field access the number of
196 | method pairs that do.
197 | Note that subsequent definitions
198 | of this metric used as a measurement basis the number
199 | of disjoint graph components of the class's methods.
200 | Others modified the definition of connectedness to
201 | include calls between the methods of the class.
202 | The program ckjm follows the original (1994) definition
203 | by Chidamber and Kemerer.
204 |
Ca - Afferent couplings
205 | A class's afferent couplings is a measure of how many other classes
206 | use the specific class.
207 | Ca is calculated using the same definition as that used for
208 | calculating CBO.
209 |
NPM - Number of Public Methods
210 | The NPM metric simply counts all the methods in a class that
211 | are declared as public.
212 | It can be used to measure the size of an API provided by a package.
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------
/contrib/ckjm_ruby-1.0/examples/util_concurrent.ckjm:
--------------------------------------------------------------------------------
1 | EDU.oswego.cs.dl.util.concurrent.WaitFreeQueue$Node 2 1 0 0 3 1 1 0
2 | EDU.oswego.cs.dl.util.concurrent.VetoableChangeMulticaster 16 1 0 0 35 18 0 12
3 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$KeyIterator 2 2 0 2 3 1 2 0
4 | EDU.oswego.cs.dl.util.concurrent.QueuedExecutor$RunLoop 2 1 0 2 6 0 1 1
5 | EDU.oswego.cs.dl.util.concurrent.SemaphoreControlledChannel 10 1 2 2 22 0 2 8
6 | EDU.oswego.cs.dl.util.concurrent.ClockDaemon 10 2 0 6 34 1 1 8
7 | EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock$ReaderSync 4 1 0 2 8 0 1 3
8 | EDU.oswego.cs.dl.util.concurrent.WaitableShort 20 3 0 1 33 0 0 20
9 | EDU.oswego.cs.dl.util.concurrent.SyncList$SyncCollectionListIterator 8 2 0 4 22 0 1 6
10 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$HashIterator 7 1 2 2 12 5 3 5
11 | EDU.oswego.cs.dl.util.concurrent.FJTask$Seq 3 2 0 1 5 0 1 3
12 | EDU.oswego.cs.dl.util.concurrent.SynchronizedInt 23 2 1 1 27 0 2 23
13 | EDU.oswego.cs.dl.util.concurrent.LinkedNode 3 1 0 0 4 1 4 3
14 | EDU.oswego.cs.dl.util.concurrent.SyncSet 5 2 1 3 13 8 2 5
15 | EDU.oswego.cs.dl.util.concurrent.CountDown 6 1 0 1 13 0 0 6
16 | EDU.oswego.cs.dl.util.concurrent.FutureResult$1 2 1 0 2 6 0 1 1
17 | EDU.oswego.cs.dl.util.concurrent.FJTaskRunner 22 1 0 3 48 53 2 1
18 | EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean 16 2 1 1 20 34 1 16
19 | EDU.oswego.cs.dl.util.concurrent.WaitableByte 20 3 0 1 33 0 0 20
20 | EDU.oswego.cs.dl.util.concurrent.Heap 11 1 0 0 16 23 2 7
21 | EDU.oswego.cs.dl.util.concurrent.ClockDaemon$RunLoop 2 1 0 2 6 0 1 1
22 | EDU.oswego.cs.dl.util.concurrent.ReaderPreferenceReadWriteLock 2 2 0 1 3 1 0 1
23 | EDU.oswego.cs.dl.util.concurrent.Puttable 2 1 0 0 2 1 1 2
24 | EDU.oswego.cs.dl.util.concurrent.WaitFreeQueue 9 1 0 2 17 18 0 6
25 | EDU.oswego.cs.dl.util.concurrent.Takable 2 1 0 0 2 1 1 2
26 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$KeySet 7 1 0 3 13 0 1 5
27 | EDU.oswego.cs.dl.util.concurrent.BrokenBarrierException 2 1 0 0 4 0 2 2
28 | EDU.oswego.cs.dl.util.concurrent.ObservableSync$SyncObserver 2 1 0 0 2 1 1 2
29 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList 42 1 0 2 78 481 3 36
30 | EDU.oswego.cs.dl.util.concurrent.FJTaskRunnerGroup 18 1 0 6 48 17 2 10
31 | EDU.oswego.cs.dl.util.concurrent.NullSync 4 1 0 1 7 6 0 4
32 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap 31 1 0 8 62 297 6 20
33 | EDU.oswego.cs.dl.util.concurrent.ThreadedExecutor 2 2 0 3 8 1 0 2
34 | EDU.oswego.cs.dl.util.concurrent.ThreadFactory 1 1 0 0 1 0 7 1
35 | EDU.oswego.cs.dl.util.concurrent.SyncCollection 22 1 2 4 47 0 5 20
36 | EDU.oswego.cs.dl.util.concurrent.ReentrantLock 6 1 0 1 15 0 0 6
37 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$BarrierLock 1 1 0 0 2 0 1 0
38 | EDU.oswego.cs.dl.util.concurrent.SynchronizedDouble 16 2 1 1 21 34 1 16
39 | EDU.oswego.cs.dl.util.concurrent.SynchronizedShort 23 2 1 1 27 0 1 23
40 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet 15 1 0 1 30 0 1 15
41 | EDU.oswego.cs.dl.util.concurrent.QueuedSemaphore$WaitQueue 3 1 2 1 4 3 5 0
42 | EDU.oswego.cs.dl.util.concurrent.PrioritySemaphore$PriorityWaitQueue 3 2 0 3 9 0 1 0
43 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$DiscardWhenBlocked 2 1 0 2 3 1 1 1
44 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$1 0 1 0 0 0 0 4 0
45 | EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock 9 1 0 5 20 0 2 3
46 | EDU.oswego.cs.dl.util.concurrent.WaitableLong 20 3 0 1 33 0 0 20
47 | EDU.oswego.cs.dl.util.concurrent.TimedCallable 2 2 0 4 10 0 0 2
48 | EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore 1 3 0 3 3 0 1 1
49 | EDU.oswego.cs.dl.util.concurrent.SynchronizedLong 23 2 1 1 27 0 3 23
50 | EDU.oswego.cs.dl.util.concurrent.ThreadFactoryUser$DefaultThreadFactory 2 1 0 1 4 1 1 1
51 | EDU.oswego.cs.dl.util.concurrent.CyclicBarrier 9 1 0 3 21 14 0 8
52 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap 34 1 0 8 66 349 6 22
53 | EDU.oswego.cs.dl.util.concurrent.SynchronizedFloat 16 2 1 1 21 34 1 16
54 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList$COWIterator 10 1 0 0 13 3 1 9
55 | EDU.oswego.cs.dl.util.concurrent.SyncSortedSet 10 3 0 3 22 39 0 9
56 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList$COWSubList$COWSubListIterator 10 1 0 2 18 19 1 9
57 | EDU.oswego.cs.dl.util.concurrent.ReadWriteLock 2 1 0 1 2 1 8 2
58 | EDU.oswego.cs.dl.util.concurrent.FJTaskRunnerGroup$InvokableFJTask 4 2 0 1 9 0 1 1
59 | EDU.oswego.cs.dl.util.concurrent.SyncList 18 2 0 4 42 127 1 17
60 | EDU.oswego.cs.dl.util.concurrent.SynchronousChannel 8 1 0 3 23 0 1 7
61 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$AbortWhenBlocked 2 1 0 2 4 1 1 1
62 | EDU.oswego.cs.dl.util.concurrent.Sync 3 1 0 0 3 3 26 3
63 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor 32 2 0 12 64 290 6 29
64 | EDU.oswego.cs.dl.util.concurrent.Channel 5 1 0 2 5 10 8 5
65 | EDU.oswego.cs.dl.util.concurrent.WaitableFloat 14 3 0 1 25 0 0 14
66 | EDU.oswego.cs.dl.util.concurrent.PropertyChangeMulticaster 16 1 0 0 34 18 0 12
67 | EDU.oswego.cs.dl.util.concurrent.WaitableDouble 14 3 0 1 25 0 0 14
68 | EDU.oswego.cs.dl.util.concurrent.Rendezvous 9 1 0 7 25 16 0 8
69 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$1 0 1 0 0 0 0 4 0
70 | EDU.oswego.cs.dl.util.concurrent.BoundedChannel 1 1 0 1 1 0 4 1
71 | EDU.oswego.cs.dl.util.concurrent.Latch 4 1 0 1 11 0 0 4
72 | EDU.oswego.cs.dl.util.concurrent.FJTaskRunner$VolatileTaskRef 5 1 0 1 6 4 1 0
73 | EDU.oswego.cs.dl.util.concurrent.ObservableSync 9 1 0 3 18 0 0 9
74 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$DiscardOldestWhenBlocked 2 1 0 3 6 0 1 1
75 | EDU.oswego.cs.dl.util.concurrent.WaitableInt 20 3 0 1 33 0 0 20
76 | EDU.oswego.cs.dl.util.concurrent.WaitableBoolean 12 3 0 1 23 0 0 12
77 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$BlockedExecutionHandler 1 1 0 0 1 0 6 1
78 | EDU.oswego.cs.dl.util.concurrent.TimeoutException 2 1 0 0 4 0 4 2
79 | EDU.oswego.cs.dl.util.concurrent.FIFOSemaphore$FIFOWaitQueue 3 2 0 2 4 0 2 0
80 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$RunWhenBlocked 2 1 0 2 4 1 1 1
81 | EDU.oswego.cs.dl.util.concurrent.TimeoutSync 4 1 0 2 8 0 0 4
82 | EDU.oswego.cs.dl.util.concurrent.SynchronousChannel$Queue 3 1 0 1 4 1 1 0
83 | EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList$COWSubList 11 1 0 2 25 0 2 8
84 | EDU.oswego.cs.dl.util.concurrent.SyncCollection$SyncCollectionIterator 4 1 1 2 15 0 2 3
85 | EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock 14 1 2 5 18 7 5 3
86 | EDU.oswego.cs.dl.util.concurrent.Semaphore 6 1 2 1 14 0 4 6
87 | EDU.oswego.cs.dl.util.concurrent.ReentrantWriterPreferenceReadWriteLock 7 2 0 4 17 0 0 1
88 | EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock$WriterLock 5 2 0 4 19 0 3 3
89 | EDU.oswego.cs.dl.util.concurrent.Slot 5 2 0 1 7 0 0 3
90 | EDU.oswego.cs.dl.util.concurrent.FJTask$Wrap 2 2 0 1 4 0 1 2
91 | EDU.oswego.cs.dl.util.concurrent.DirectExecutor 2 1 0 1 6 1 0 2
92 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$Entry 7 1 0 0 17 0 2 6
93 | EDU.oswego.cs.dl.util.concurrent.Mutex 4 1 0 1 11 0 0 4
94 | EDU.oswego.cs.dl.util.concurrent.LayeredSync 4 1 0 1 9 0 0 4
95 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker 2 1 0 1 6 0 1 1
96 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$EntrySet 7 1 0 3 16 0 1 5
97 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$Segment 3 1 0 0 4 3 2 0
98 | EDU.oswego.cs.dl.util.concurrent.WaitableRef 8 3 0 1 15 0 0 8
99 | EDU.oswego.cs.dl.util.concurrent.Rendezvous$Rotator 2 1 0 1 3 1 1 2
100 | EDU.oswego.cs.dl.util.concurrent.SyncMap 22 1 1 5 49 0 1 20
101 | EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock$ReaderLock 5 2 0 4 19 0 3 3
102 | EDU.oswego.cs.dl.util.concurrent.Rendezvous$RendezvousFunction 1 1 0 0 1 0 2 1
103 | EDU.oswego.cs.dl.util.concurrent.Callable 1 1 0 0 1 0 3 1
104 | EDU.oswego.cs.dl.util.concurrent.SynchronizedByte 23 2 1 1 27 0 1 23
105 | EDU.oswego.cs.dl.util.concurrent.SynchronizedVariable 4 1 9 1 8 0 9 4
106 | EDU.oswego.cs.dl.util.concurrent.LinkedQueue 9 1 0 2 18 12 1 7
107 | EDU.oswego.cs.dl.util.concurrent.PrioritySemaphore 1 3 0 3 3 0 0 1
108 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$KeyIterator 2 2 0 2 3 1 2 0
109 | EDU.oswego.cs.dl.util.concurrent.ClockDaemon$TaskNode 7 1 0 0 8 9 2 1
110 | EDU.oswego.cs.dl.util.concurrent.Executor 1 1 0 0 1 0 7 1
111 | EDU.oswego.cs.dl.util.concurrent.LockedExecutor 2 1 0 2 6 0 0 2
112 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$ValueIterator 2 2 0 2 3 1 2 0
113 | EDU.oswego.cs.dl.util.concurrent.BoundedLinkedQueue 15 1 0 3 26 29 1 11
114 | EDU.oswego.cs.dl.util.concurrent.WaiterPreferenceSemaphore 5 2 0 1 12 0 1 5
115 | EDU.oswego.cs.dl.util.concurrent.DefaultChannelCapacity 4 1 0 1 9 0 4 3
116 | EDU.oswego.cs.dl.util.concurrent.FJTask 18 1 6 6 32 147 9 17
117 | EDU.oswego.cs.dl.util.concurrent.SynchronizedRef 6 2 1 1 9 0 1 6
118 | EDU.oswego.cs.dl.util.concurrent.FJTask$Par 3 2 0 1 5 0 1 3
119 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$KeySet 7 1 0 3 13 0 1 5
120 | EDU.oswego.cs.dl.util.concurrent.PooledExecutor$WaitWhenBlocked 2 1 0 3 4 0 1 1
121 | EDU.oswego.cs.dl.util.concurrent.ThreadFactoryUser 3 1 5 2 5 0 5 3
122 | EDU.oswego.cs.dl.util.concurrent.FutureResult 11 1 0 3 19 0 2 10
123 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$Values 6 1 0 3 11 0 1 4
124 | EDU.oswego.cs.dl.util.concurrent.BoundedPriorityQueue 8 2 0 3 15 8 0 6
125 | EDU.oswego.cs.dl.util.concurrent.SyncSortedMap 10 2 0 3 21 39 0 9
126 | EDU.oswego.cs.dl.util.concurrent.QueuedExecutor 10 2 0 7 20 7 1 8
127 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$HashIterator 7 1 2 3 12 5 3 5
128 | EDU.oswego.cs.dl.util.concurrent.FJTask$Par2 2 2 0 1 4 0 1 2
129 | EDU.oswego.cs.dl.util.concurrent.Barrier 2 1 0 0 2 1 2 2
130 | EDU.oswego.cs.dl.util.concurrent.FJTask$Seq2 2 2 0 1 4 0 1 2
131 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$ValueIterator 2 2 0 2 3 1 2 0
132 | EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap$Values 6 1 0 3 11 0 1 4
133 | EDU.oswego.cs.dl.util.concurrent.BoundedBuffer 13 1 0 2 22 4 0 9
134 | EDU.oswego.cs.dl.util.concurrent.QueuedSemaphore$WaitQueue$WaitNode 4 1 0 1 12 0 4 0
135 | EDU.oswego.cs.dl.util.concurrent.FIFOReadWriteLock$WriterSync 4 1 0 2 8 0 1 3
136 | EDU.oswego.cs.dl.util.concurrent.QueuedExecutor$1 2 1 0 0 3 1 1 1
137 | EDU.oswego.cs.dl.util.concurrent.CondVar 5 1 0 1 17 4 0 5
138 | EDU.oswego.cs.dl.util.concurrent.SynchronizedChar 16 2 1 1 20 34 1 16
139 | EDU.oswego.cs.dl.util.concurrent.WaitableChar 14 3 0 1 25 0 0 14
140 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$Entry 7 1 0 0 17 0 2 6
141 | EDU.oswego.cs.dl.util.concurrent.QueuedSemaphore 8 2 2 3 18 18 3 4
142 | EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap$EntrySet 7 1 0 3 16 0 1 5
143 | EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock$Signaller 2 1 2 1 3 1 4 0
144 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2005-2016 Diomidis Spinellis
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/lib/LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*
2 | * Apache License
3 | * Version 2.0, January 2004
4 | * http://www.apache.org/licenses/
5 | *
6 | * TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 | *
8 | * 1. Definitions.
9 | *
10 | * "License" shall mean the terms and conditions for use, reproduction,
11 | * and distribution as defined by Sections 1 through 9 of this document.
12 | *
13 | * "Licensor" shall mean the copyright owner or entity authorized by
14 | * the copyright owner that is granting the License.
15 | *
16 | * "Legal Entity" shall mean the union of the acting entity and all
17 | * other entities that control, are controlled by, or are under common
18 | * control with that entity. For the purposes of this definition,
19 | * "control" means (i) the power, direct or indirect, to cause the
20 | * direction or management of such entity, whether by contract or
21 | * otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | * outstanding shares, or (iii) beneficial ownership of such entity.
23 | *
24 | * "You" (or "Your") shall mean an individual or Legal Entity
25 | * exercising permissions granted by this License.
26 | *
27 | * "Source" form shall mean the preferred form for making modifications,
28 | * including but not limited to software source code, documentation
29 | * source, and configuration files.
30 | *
31 | * "Object" form shall mean any form resulting from mechanical
32 | * transformation or translation of a Source form, including but
33 | * not limited to compiled object code, generated documentation,
34 | * and conversions to other media types.
35 | *
36 | * "Work" shall mean the work of authorship, whether in Source or
37 | * Object form, made available under the License, as indicated by a
38 | * copyright notice that is included in or attached to the work
39 | * (an example is provided in the Appendix below).
40 | *
41 | * "Derivative Works" shall mean any work, whether in Source or Object
42 | * form, that is based on (or derived from) the Work and for which the
43 | * editorial revisions, annotations, elaborations, or other modifications
44 | * represent, as a whole, an original work of authorship. For the purposes
45 | * of this License, Derivative Works shall not include works that remain
46 | * separable from, or merely link (or bind by name) to the interfaces of,
47 | * the Work and Derivative Works thereof.
48 | *
49 | * "Contribution" shall mean any work of authorship, including
50 | * the original version of the Work and any modifications or additions
51 | * to that Work or Derivative Works thereof, that is intentionally
52 | * submitted to Licensor for inclusion in the Work by the copyright owner
53 | * or by an individual or Legal Entity authorized to submit on behalf of
54 | * the copyright owner. For the purposes of this definition, "submitted"
55 | * means any form of electronic, verbal, or written communication sent
56 | * to the Licensor or its representatives, including but not limited to
57 | * communication on electronic mailing lists, source code control systems,
58 | * and issue tracking systems that are managed by, or on behalf of, the
59 | * Licensor for the purpose of discussing and improving the Work, but
60 | * excluding communication that is conspicuously marked or otherwise
61 | * designated in writing by the copyright owner as "Not a Contribution."
62 | *
63 | * "Contributor" shall mean Licensor and any individual or Legal Entity
64 | * on behalf of whom a Contribution has been received by Licensor and
65 | * subsequently incorporated within the Work.
66 | *
67 | * 2. Grant of Copyright License. Subject to the terms and conditions of
68 | * this License, each Contributor hereby grants to You a perpetual,
69 | * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | * copyright license to reproduce, prepare Derivative Works of,
71 | * publicly display, publicly perform, sublicense, and distribute the
72 | * Work and such Derivative Works in Source or Object form.
73 | *
74 | * 3. Grant of Patent License. Subject to the terms and conditions of
75 | * this License, each Contributor hereby grants to You a perpetual,
76 | * worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | * (except as stated in this section) patent license to make, have made,
78 | * use, offer to sell, sell, import, and otherwise transfer the Work,
79 | * where such license applies only to those patent claims licensable
80 | * by such Contributor that are necessarily infringed by their
81 | * Contribution(s) alone or by combination of their Contribution(s)
82 | * with the Work to which such Contribution(s) was submitted. If You
83 | * institute patent litigation against any entity (including a
84 | * cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | * or a Contribution incorporated within the Work constitutes direct
86 | * or contributory patent infringement, then any patent licenses
87 | * granted to You under this License for that Work shall terminate
88 | * as of the date such litigation is filed.
89 | *
90 | * 4. Redistribution. You may reproduce and distribute copies of the
91 | * Work or Derivative Works thereof in any medium, with or without
92 | * modifications, and in Source or Object form, provided that You
93 | * meet the following conditions:
94 | *
95 | * (a) You must give any other recipients of the Work or
96 | * Derivative Works a copy of this License; and
97 | *
98 | * (b) You must cause any modified files to carry prominent notices
99 | * stating that You changed the files; and
100 | *
101 | * (c) You must retain, in the Source form of any Derivative Works
102 | * that You distribute, all copyright, patent, trademark, and
103 | * attribution notices from the Source form of the Work,
104 | * excluding those notices that do not pertain to any part of
105 | * the Derivative Works; and
106 | *
107 | * (d) If the Work includes a "NOTICE" text file as part of its
108 | * distribution, then any Derivative Works that You distribute must
109 | * include a readable copy of the attribution notices contained
110 | * within such NOTICE file, excluding those notices that do not
111 | * pertain to any part of the Derivative Works, in at least one
112 | * of the following places: within a NOTICE text file distributed
113 | * as part of the Derivative Works; within the Source form or
114 | * documentation, if provided along with the Derivative Works; or,
115 | * within a display generated by the Derivative Works, if and
116 | * wherever such third-party notices normally appear. The contents
117 | * of the NOTICE file are for informational purposes only and
118 | * do not modify the License. You may add Your own attribution
119 | * notices within Derivative Works that You distribute, alongside
120 | * or as an addendum to the NOTICE text from the Work, provided
121 | * that such additional attribution notices cannot be construed
122 | * as modifying the License.
123 | *
124 | * You may add Your own copyright statement to Your modifications and
125 | * may provide additional or different license terms and conditions
126 | * for use, reproduction, or distribution of Your modifications, or
127 | * for any such Derivative Works as a whole, provided Your use,
128 | * reproduction, and distribution of the Work otherwise complies with
129 | * the conditions stated in this License.
130 | *
131 | * 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | * any Contribution intentionally submitted for inclusion in the Work
133 | * by You to the Licensor shall be under the terms and conditions of
134 | * this License, without any additional terms or conditions.
135 | * Notwithstanding the above, nothing herein shall supersede or modify
136 | * the terms of any separate license agreement you may have executed
137 | * with Licensor regarding such Contributions.
138 | *
139 | * 6. Trademarks. This License does not grant permission to use the trade
140 | * names, trademarks, service marks, or product names of the Licensor,
141 | * except as required for reasonable and customary use in describing the
142 | * origin of the Work and reproducing the content of the NOTICE file.
143 | *
144 | * 7. Disclaimer of Warranty. Unless required by applicable law or
145 | * agreed to in writing, Licensor provides the Work (and each
146 | * Contributor provides its Contributions) on an "AS IS" BASIS,
147 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | * implied, including, without limitation, any warranties or conditions
149 | * of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | * PARTICULAR PURPOSE. You are solely responsible for determining the
151 | * appropriateness of using or redistributing the Work and assume any
152 | * risks associated with Your exercise of permissions under this License.
153 | *
154 | * 8. Limitation of Liability. In no event and under no legal theory,
155 | * whether in tort (including negligence), contract, or otherwise,
156 | * unless required by applicable law (such as deliberate and grossly
157 | * negligent acts) or agreed to in writing, shall any Contributor be
158 | * liable to You for damages, including any direct, indirect, special,
159 | * incidental, or consequential damages of any character arising as a
160 | * result of this License or out of the use or inability to use the
161 | * Work (including but not limited to damages for loss of goodwill,
162 | * work stoppage, computer failure or malfunction, or any and all
163 | * other commercial damages or losses), even if such Contributor
164 | * has been advised of the possibility of such damages.
165 | *
166 | * 9. Accepting Warranty or Additional Liability. While redistributing
167 | * the Work or Derivative Works thereof, You may choose to offer,
168 | * and charge a fee for, acceptance of support, warranty, indemnity,
169 | * or other liability obligations and/or rights consistent with this
170 | * License. However, in accepting such obligations, You may act only
171 | * on Your own behalf and on Your sole responsibility, not on behalf
172 | * of any other Contributor, and only if You agree to indemnify,
173 | * defend, and hold each Contributor harmless for any liability
174 | * incurred by, or claims asserted against, such Contributor by reason
175 | * of your accepting any such warranty or additional liability.
176 | *
177 | * END OF TERMS AND CONDITIONS
178 | *
179 | * APPENDIX: How to apply the Apache License to your work.
180 | *
181 | * To apply the Apache License to your work, attach the following
182 | * boilerplate notice, with the fields enclosed by brackets "[]"
183 | * replaced with your own identifying information. (Don't include
184 | * the brackets!) The text should be enclosed in the appropriate
185 | * comment syntax for the file format. We also recommend that a
186 | * file or class name and description of purpose be included on the
187 | * same "printed page" as the copyright notice for easier
188 | * identification within third-party archives.
189 | *
190 | * Copyright [yyyy] [name of copyright owner]
191 | *
192 | * Licensed under the Apache License, Version 2.0 (the "License");
193 | * you may not use this file except in compliance with the License.
194 | * You may obtain a copy of the License at
195 | *
196 | * http://www.apache.org/licenses/LICENSE-2.0
197 | *
198 | * Unless required by applicable law or agreed to in writing, software
199 | * distributed under the License is distributed on an "AS IS" BASIS,
200 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | * See the License for the specific language governing permissions and
202 | * limitations under the License.
203 | */
204 |
205 |
--------------------------------------------------------------------------------