Giter Club home page Giter Club logo

japi-compliance-checker's Introduction

JAPICC 2.4

Java API Compliance Checker (JAPICC) — a tool for checking backward binary and source-level compatibility of a Java library API.

Contents

  1. About
  2. Install
  3. Usage
  4. Test suite

About

The tool checks classes declarations of old and new versions and analyzes changes that may break compatibility: removed methods, removed class fields, added abstract methods, etc. The tool is intended for developers of software libraries and Linux maintainers who are interested in ensuring backward compatibility.

The Scala language is supported since 1.7 version of the tool.

Java 9 is supported since 2.4 version of the tool.

The tool is a core of the Java API Tracker project: https://abi-laboratory.pro/java/tracker/

Install

sudo make install prefix=/usr
Requires
  • JDK or OpenJDK - development files
  • Perl 5

Usage

japi-compliance-checker OLD.jar NEW.jar
Java 9
japi-compliance-checker OLD.jmod NEW.jmod
Create API dumps
japi-compliance-checker -dump LIB.jar -dump-path ./API.dump
japi-compliance-checker API-0.dump API-1.dump
Adv. usage

For advanced usage, see doc/index.html or output of -help option.

Test suite

The tool is tested properly in the Java API Tracker project, by the community and by the internal test suite:

japi-compliance-checker -test

There are about 100 basic tests in the test suite.

japi-compliance-checker's People

Contributors

aponomarenko avatar laurentgo avatar lvc avatar pkgdiff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

japi-compliance-checker's Issues

ERROR: internal error in parser

main::mergeTypes() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 1105 (#1)
    (W prototype) You've called a function that has a prototype before the
    parser saw a definition or declaration for it, and Perl could not check
    that the call conforms to the prototype.  You need to either add an
    early prototype declaration for the subroutine in question, or move the
    subroutine definition ahead of the call to get proper prototype
    checking.  Alternatively, if you are certain that you're calling the
    function correctly, you may put an ampersand before the name to avoid
    the warning.  See perlsub.

main::mergeTypes() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 1583 (#1)
main::findMethod() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 1728 (#1)
main::getModules() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 55 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 60 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 61 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 62 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 63 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 64 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 65 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 66 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 67 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 68 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 69 (#1)
main::errMsg() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 158 (#1)
main::errMsg() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 169 (#1)
main::getBaseType() called too early to check prototype at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/TypeAttr.pm line 71 (#1)
Using Java 1.8.0_192

Verifying detectable Java library changes
Creating test library ...
Picked up JAVA_TOOL_OPTIONS:
Picked up JAVA_TOOL_OPTIONS:
Picked up JAVA_TOOL_OPTIONS:
Picked up JAVA_TOOL_OPTIONS:
Picked up JAVA_TOOL_OPTIONS:
Picked up JAVA_TOOL_OPTIONS:
Running tests ...
Picked up JAVA_TOOL_OPTIONS:
See journal with test results: libsample_java/Tests/Journal.txt
main::mergeTypes() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 1105 (#1)
    (W prototype) You've called a function that has a prototype before the
    parser saw a definition or declaration for it, and Perl could not check
    that the call conforms to the prototype.  You need to either add an
    early prototype declaration for the subroutine in question, or move the
    subroutine definition ahead of the call to get proper prototype
    checking.  Alternatively, if you are certain that you're calling the
    function correctly, you may put an ampersand before the name to avoid
    the warning.  See perlsub.

main::mergeTypes() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 1583 (#1)
main::findMethod() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 1728 (#1)
main::getModules() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 55 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 60 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 61 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 62 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 63 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 64 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 65 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 66 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 67 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 68 (#1)
main::loadModule() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 69 (#1)
main::errMsg() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 158 (#1)
main::errMsg() called too early to check prototype at
	/usr/bin/japi-compliance-checker line 169 (#1)
main::getBaseType() called too early to check prototype at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/TypeAttr.pm line 71 (#1)
Preparing, please wait ...

Use of uninitialized value $Java in hash element at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/SysFiles.pm line 152 (#2)
    (W uninitialized) An undefined value was used as if it were already
    defined.  It was interpreted as a "" or a 0, but maybe it was a mistake.
    To suppress this warning assign a defined value to your variables.

    To help you figure out what was undefined, perl will try to tell you
    the name of the variable (if any) that was undefined.  In some cases
    it cannot do this, so it also tells you what operation you used the
    undefined value in.  Note, however, that perl optimizes your program
    and the operation displayed in the warning may not necessarily appear
    literally in your program.  For example, "that $foo" is usually
    optimized into "that " . $foo, and the warning will refer to the
    concatenation (.) operator, even though there is no . in
    your program.

Use of uninitialized value $Java in hash element at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/SysFiles.pm line 156 (#2)
main::readArchive() called too early to check prototype at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/APIDump.pm line 202 (#1)
main::readArchive() called too early to check prototype at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/APIDump.pm line 207 (#1)
main::registerType() called too early to check prototype at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/APIDump.pm line 1074 (#1)
main::registerType() called too early to check prototype at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/APIDump.pm line 1082 (#1)
Use of uninitialized value $Bin in hash element at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/SysFiles.pm line 152 (#2)
Use of uninitialized value $Bin in hash element at
	/usr/bin/../share/japi-compliance-checker/modules/Internals/SysFiles.pm line 156 (#2)
Using Java 1.8.0_192
Reading classes 1.0 ...
Picked up JAVA_TOOL_OPTIONS:
ERROR: internal error in parser
ERROR: analysis has failed```

Deprecated annotation on class is not accounted for on method level

Between Apache Hadoop 2.7.2 and 3.0.0-alpha2 (trunk), we removed a class that looked like this:

@Deprecated
@InterfaceAudience.Public
@InterfaceStability.Stable
public class RccTask extends Task {

Deprecation here is marked only on the class, not on any of its methods.

JACC 1.8 is picking up each of the methods in RccTask as a removed, but is not marking them as deprecated like it does when an individual method is annotated as deprecated.

packages option in XML descriptor doesn't work

I have the following descriptors

new.xml

<version>
2.2.4-SNAPSHOT
</version>

<archives>
f:\src\.\g4q6zTNi\com.x.y-2.2.4-SNAPSHOT.jar
</archives>

<packages>
com.x.y.framework
</packages> 

old.xml

<version>
2.2.3.20150421-1400
</version>

<archives>
f:\src\.\g4q6zTNi\com.x.y-2.2.3.20150421-1400.jar
</archives>

<packages>
com.x.y.framework
</packages> 

command-line

japi-compliance-checker.pl -lib com.x.y -old old.xml -new new.xml

This generates an empty report. If the tags are removed the report is ok and there are incompatibilities found in the given package.

Thanks!

Very nice tool indeed!

Command line is too long

The tool runs well for simple cases, but rapidly fails with larger data sets. We have one jar file with 2426 java files for example. The error is shown below comparing v2.0.0 with v2.1.0-RC1.

The command line is too long.
ERROR: internal error in parser, try to reduce MAX_ARGS

It looks like it is caused by passing each file to javap on one long command line. As such, this might be a Windows only issue. It is a pain though...

Method incorrectly reported as removed

I work on the mockito project and noticed a release that has backward compatibility issue (report on ABI-Laboratory), while the only changes were :

- Answer1<T,A>.answer(A p1)
+ Answer1<T,A0>.answer(A0 p1) throws Throwable 
  • renamed the type parameters
  • added throws declaration

These methods should not be reported as removed, as the type parameter renaming is binary compatible, and the throws declaration is compiler visible only but it is backward compatible.

Not working with Java8

I'm getting empty reports when run with Java8. Specifically, Oracle jdk1.8.0_65 on OSX and OpenJDk 1.8.0_45-internal-b14 on ubuntu. I'm afraid it's not much to do on, but I did file HBASE-14933 for tracking any necessary changes on our end.

Support for Java 9

For now the tool checks classes of a project by extracting *.jar files to /tmp/XYZ directory and disassembling *.class files by javap. This works for Java 1-8.

In Java 9 we need to support modules. The tool should be able to compare modules instead of *.jar files.

One can list classes in the module file by this command:

jimage list ./modules

...
/jdk.zipfs/jdk/nio/zipfs/ZipFileSystem.class
/jdk.zipfs/jdk/nio/zipfs/ZipFileSystemProvider.class
/jdk.zipfs/jdk/nio/zipfs/ZipInfo.class
/jdk.zipfs/jdk/nio/zipfs/ZipPath$1.class
/jdk.zipfs/jdk/nio/zipfs/ZipPath$2.class
/jdk.zipfs/jdk/nio/zipfs/ZipPath.class
/jdk.zipfs/jdk/nio/zipfs/ZipUtils.class
/jdk.zipfs/module-info.class
...

And then we can run javap against one of them:

javap jrt:/jdk.zipfs/jdk/nio/zipfs/ZipInfo.class

Compiled from "ZipInfo.java"
public class jdk.nio.zipfs.ZipInfo {
  public jdk.nio.zipfs.ZipInfo();
  public static void main(java.lang.String[]) throws java.lang.Throwable;
  static void print(java.lang.String, java.lang.Object...);
  static void printLOC(byte[]);
  static void printCEN(byte[], int);
  static long locoff(byte[], int);
  static void printExtra(byte[], int, int);
}

So we just need to replace the extracting of jar by listing the module and add jrt:/ prefix to class paths.

Addition of class type parameter to super-interface marked as removal

I found this while comparing Apache Hadoop 2.7.2 with 3.0.0-alpha2 (trunk).

We have a class that looked like this in 2.7.2:

public class FileStatus implements Writable, Comparable {

We changed it to this:

public class FileStatus implements Writable, Comparable<FileStatus> {

I think this is compatible based on my read of https://docs.oracle.com/javase/specs/jls/se7/html/jls-13.html#jls-13.4.5 . In any case, JACC says that Comparable was removed, which isn't quite accurate.

False positive, removed super interface when class still indirectly extends interface

We saw a false positive report of source / binary incompatibility

The class in question directly extended the interfaces Feature and Locatable

We had a hierarchy like this:

interface Locatable
interface Feature extends Locatable
class Interval implements Locatable, Feature

In a new version we changed Interval so it no longer directly extends Locatable but still extends it through Feature.

We (incorrectly) get the following error:
High severity: Removed super-interface Locatable.

passing comma separated list of jars broken

looks like the change in commit e206a1d broke the ability to pass a comma separated list of jars instead of a descriptor file.

with that change in place, when I give a list of jars I get this error:

Running the Java API Compliance Checker...
ERROR: can't access './target/compatibility/1/hbase-annotations/target/hbase-annotations-1.2.1.jar,./target/compatibility/1/hbase-checkstyle/target/hbase-checkstyle-1.2.1.jar,./target/compatibility/1/hbase-client/target/hbase-client-1.2.1.jar,./target/compatibility/1/hbase-common/target/hbase-common-1.2.1.jar,./target/compatibility/1/hbase-examples/target/hbase-examples-1.2.1.jar,./target/compatibility/1/hbase-external-blockcache/target/hbase-external-blockcache-1.2.1.jar,./target/compatibility/1/hbase-hadoop-compat/target/hbase-hadoop-compat-1.2.1.jar,./target/compatibility/1/hbase-hadoop2-compat/target/hbase-hadoop2-compat-1.2.1.jar,./target/compatibility/1/hbase-it/target/hbase-it-1.2.1.jar,./target/compatibility/1/hbase-prefix-tree/target/hbase-prefix-tree-1.2.1.jar,./target/compatibility/1/hbase-procedure/target/hbase-procedure-1.2.1.jar,./target/compatibility/1/hbase-protocol/target/hbase-protocol-1.2.1.jar,./target/compatibility/1/hbase-resource-bundle/target/hbase-resource-bundle-1.2.1.jar,./target/compatibility/1/hbase-rest/target/hbase-rest-1.2.1.jar,./target/compatibility/1/hbase-server/target/hbase-server-1.2.1.jar,./target/compatibility/1/hbase-shell/target/hbase-shell-1.2.1.jar,./target/compatibility/1/hbase-testing-util/target/hbase-testing-util-1.2.1.jar,./target/compatibility/1/hbase-thrift/target/hbase-thrift-1.2.1.jar'

If I go back to prior to that commit then the list of jars is properly handled.

the invocation is in this hbase script for building the list of jars

Missed source compatibility problem with ambiguous overloads.

When adding additional overloads that have the same number of parameters to an existing method, it causes a potential source compatibility issue due to the type inference of null.

ex:
Existing method

public void doThing(File file){...}

Adding the following overload will cause compilation errors in sites that make a call with a null parameter.

public void doThing(Path path){...}

Annotations list isn't working

Sometime since v1.4.3 of this tool, support for listing annotations to analyze appears to have broken. To repro, checkout the master branch of the tool and then do as follows:

  • Pull down two JARs. As an example, try hbase-server v1.1.3 and hbase-server v.1.2.0.
  • Run the tool between the two JARs. Verify that methods and classes are properly read.
  • Now populate an annotations file. I create one that limits to Public and LimitedPrivate interfaces:
dspivak-MBP:javaACC dspivak$ cat list
InterfaceAudience.Public
InterfaceAudience.LimitedPrivate
  • Re-run the tool, specifying -annotations-list to point to the file. On my machine:
perl japi-compliance-checker.pl -annotations-list list /Users/dspivak/Desktop/hbase-server-1.1.3.jar /Users/dspivak/Desktop/hbase-server-1.2.1.jar 
  • The report generated shows that no methods or classes were read.

Comparing API dumps fails on Mac OS X

On Mac OS X, comparing API dumps fails as follows:

[sekikn@mobile ~]$ uname -a
Darwin mobile.local 15.0.0 Darwin Kernel Version 15.0.0: Sat Sep 19 15:53:46 PDT 2015; root:xnu-3247.10.11~1/RELEASE_X86_64 x86_64
[sekikn@mobile japi-compliance-checker]$ japi-compliance-checker -v
Java API Compliance Checker (Java ACC) 1.4.3
Copyright (C) 2015 Andrey Ponomarenko's ABI Laboratory
License: LGPL or GPL <http://www.gnu.org/licenses/>
This program is free software: you can redistribute it and/or modify it.

Written by Andrey Ponomarenko.
[sekikn@mobile ~]$ japi-compliance-checker -dump /usr/local/Cellar/hadoop/2.6.0/libexec/share/hadoop/common/hadoop-common-2.6.0.jar
using Java 1.7.0_80
reading classes 2.6.0 ...
WARNING: skip "impl" packages (use --keep-internal option to check them)
creating library API dump ...
library API has been dumped to:
  api_dumps/hadoop-common/hadoop-common_2.6.0.api.tar.gz
you can transfer this dump everywhere and use instead of the 2.6.0 version descriptor
[sekikn@mobile ~]$ japi-compliance-checker -dump /usr/local/Cellar/hadoop/2.7.1/libexec/share/hadoop/common/hadoop-common-2.7.1.jar 
using Java 1.7.0_80
reading classes 2.7.1 ...
WARNING: skip "impl" packages (use --keep-internal option to check them)
creating library API dump ...
library API has been dumped to:
  api_dumps/hadoop-common/hadoop-common_2.7.1.api.tar.gz
you can transfer this dump everywhere and use instead of the 2.7.1 version descriptor
[sekikn@mobile ~]$ japi-compliance-checker -l hadoop-common api_dumps/hadoop-common/hadoop-common_2.6.0.api.tar.gz api_dumps/hadoop-common/hadoop-common_2.7.1.api.tar.gz 
using Java 1.7.0_80
x hadoop-common_2.6.0.api
ERROR: can't extract '/Users/sekikn/api_dumps/hadoop-common/hadoop-common_2.6.0.api.tar.gz'

This is because OS X uses BSD tar rather than GNU tar, and it outputs the extracted filenames to stderr instead of stdout, with preceding "x".

-client option doesn't work

This option doesn't take into account some classes used in the client. Also it doesn't handle $ symbol in class names.

Show method accessibility in report

It would be nice if the report showed method accessibility. When I see that a method was removed, I would like to know if its public or protected.

Consider deprecated methods

It would be nice if this tool took deprecation into account. I want to find non-deprecated methods that were removed. I am ok with deprecated methods being removed.

Abstract_Class_Added_Super_Interface thrown when not appropriate

I'm having dual unnecessary instances of Abstract_Class_Added_Super_Interface being thrown.

The first reason why it's unnecessary is that all of the methods in my interface are Java 8 default methods. Meaning that there will never be a case where a child class will get an Unimplemented Abstract Method error.

And the second reason is that this error is unnecessary is because the class I added the implementation to already has all of the implementations methods overwritten. Therefore, there is, again, no way for the child to need to worry about overwriting it.

Are my expectations of this utility missing the mark or are these actually in error?

symlinks are not resolved, but are processed

Hello! The symlinks are considered as files, and so duplicated files are processed as real. So if I link N links to file X and compare versions of 1 and 2, (N1+1)x(N2+1) comaprsions is actualy done instead of one.

I'm not saying that it is bug, but maybe switch to skip symlinks may be included. Thanx!

is -client option working ?

Hi,

As a small testcase i created a v1 and v2 version of a 1-method interface, v2 having a changed signature. When i run this through japi it says that both versions are not binary compatible, as expected. But when i then add the -client option and point to a simple java class that uses the v1 interface it says that no incompatibilities have been detected. I would have expected something in the report saying that my class is not compatible with the v2 interface. Or am i missing something ? I can attach my simple testcase and commands used if required.

oh and thanks for such a great tool !

Jorg

Corrupted output when type is generic

I observed that the output of japi-compliance-checker is sometimes corrupted when types are generic.

Example of such output (as returned by the browser):

<div class='affected'><span class='nblack'>ConfigModelBuilder&lt;T.build&#160;<span class='sym_p'>(&#160;com.yahoo.config.model.application.ApplicationPackage <span class='param'>applicationPackage</span>, com.yahoo.config.model.producer.AbstractConfigProducer <span class='param'>parent</span>, <span class='nowrap'>org.w3c.dom.Element <span class='param'>spec</span> )</span></span></span><br/><div class='affect'>This method is from 'ConfigModelBuilder<T' abstract class.</div> 

False report of binary incompatibility when generifying method

I have the following class:

public abstract Foo {
  Foo() {}

  public abstract Foo doSomething();

  public static Foo create() {
    return new SomePrivateSubclassOfFoo();
  }
}

When I change it to the following, japi-compliance-checker 2.0 claims binary incompatibility because it says Foo doSomething() got removed and T doSomething() got added:

public abstract Foo<T extends Foo<T>> {
  Foo() {}

  public abstract T doSomething();

  public static Foo<?> create() {
    return new SomePrivateSubclassOfFoo();
  }
}

However, because the erasure of T is Foo, this is binary compatible as explained here.

Classes with the same full name in different libraries

I have using your wonderful tool to detect the breaking compatibility changes in my framework.
By pattern, my framework happens to have the same classes (for different implementations) in different jars.

Ex: LoggerSpring4 and LoggerSpring5. Both with the same package and name but in different jars (one for spring 4 and one for spring5).

I ran your product and the results seem to be a little weird (even if it does not make it crash). I assume you did not take into account that use case.

Could you confirm my assumption ? And if yes, would it be possible to fix that ? Basically handle this usecase.

Covariant return type causes false positive for method removal due to return type change.

Over in Apache HBase we had a change (509c1b63) that added a method to a supertype of a class such that the original class' method became an override via covariant return type.

In summary, before the change:

class Query {}

class Scan extends Query {
  public Scan setLoadColumnFamiliesOnDemand(boolean value);
}

and after the change:

class Query {
  public Query setLoadColumnFamiliesOnDemand(boolean value);
}

class Scan extends Query {
  public Scan setLoadColumnFamiliesOnDemand(boolean value);
}

Using japi-compliance-checker 2.4, this gets reported as a change in return type that will cause a High Severity binary compatibility problem for MethodNotFoundException and a Medium Severity source compatibility problem for downstream users.

e.g.

Problems with Methods, High Severity  1 


  hbase-client-1.2.6.jar, Scan.class
  package org.apache.hadoop.hbase.client
  [+] Scan.setLoadColumnFamiliesOnDemand ( boolean value )  :  Scan  1   
 
  org/apache/hadoop/hbase/client/Scan.setLoadColumnFamiliesOnDemand:(Z)Lorg/apache/hadoop/hbase/client/Scan;
           
ChangeEffect
1Return value type has been changed from Scan to Query.This method has been removed because the return type is part of the method signature. A client program may be interrupted by NoSuchMethodError exception.

 
Examining the class file for the updated Scan class shows that since the method now has a covariant return type two method signatures are included:

busbey$ javap -cp target/compat-check/dst/hbase-client/target/hbase-client-1.2.7.jar org.apache.hadoop.hbase.client.Scan | grep setLoadColumnFamiliesOnDemand
  public org.apache.hadoop.hbase.client.Scan setLoadColumnFamiliesOnDemand(boolean);
  public org.apache.hadoop.hbase.client.Query setLoadColumnFamiliesOnDemand(boolean);

japi-compliance-checker appears to mistakenly just pick up the second method signature and thus the compatibility issues.

annotation-based filtering not removing classes as expected

I have an example run using the 2.1 release that is showing incompatible changes for a class that I believe should be filtered out.

I'm checking on the compatibility of change b8ad9b1 in hbase. Note that the only change is to a class with the annotation InterfaceAudience.Private.

Here's how I'm invoking things, which I believe should restrict checking to just classes marked with InterfaceAudience.Public and InterfaceAudience.LimitedPrivate:

$ perl ./target/java-acc/japi-compliance-checker.pl -version
Java API Compliance Checker (JAPICC) 2.1

$ perl target/java-acc/japi-compliance-checker.pl -l hbase -d1 target/compat-check/src.xml \
-d2 target/compat-check/dst.xml -report-path target/compat-check/report.html \
-annotations-list target/compat-check/annotations.txt \
-skip-annotations-list target/compat-check/skip_annotations.txt

$ cat target/compat-check/annotations.txt 
org.apache.hadoop.hbase.classification.InterfaceAudience.Public
org.apache.hadoop.hbase.classification.InterfaceAudience.LimitedPrivate

$ cat target/compat-check/skip_annotations.txt
org.apache.hadoop.hbase.classification.InterfaceAudience.Private

The resultant report shows incompatible changes to the class from the commit.

Possible to get report in JSON format?

I just want to extract the incompatibilities in JSON format.
So is there any flag available which I can give while running the compliance checker tool?

warnings on solaris

Hi,

running the tool on our solaris machine i get some warnings:

reading classes 1.7.1 ...
Can't stat /tmp/JI6mi4GHXP/0 (No such file or directory) at ./japi-compliance-checker line 6096
..
Can't stat /tmp/JI6mi4GHXP/class-dump.txt (No such file or directory) at ./japi-compliance-checker line 6306
reading classes 1.8.3 ...
Can't stat /tmp/JI6mi4GHXP/1 (No such file or directory) at ./japi-compliance-checker line 6096

The report seems to have been generated fine though, so this might be harmless.

Java 8 compatibility

Hi,

I have the following error when using japi-compliance-checker with OpenJDK 8:

ebourg@icare:~/japi-compliance-checker$ ./japi-compliance-checker.pl -test

verifying detectable Java library changes
reading classes 1.0 ...
ERROR: internal error - can't read method signature

Also, the output of java -version changed in OpenJDK 8 and the regexp detecting the version used has to be updated:

if(my $JavaCmd = get_CmdPath("java"))
{
    if(my $Ver = `$JavaCmd -version 2>&1`)
    {
        if($Ver=~/(java|openjdk) version "(.+)\"/) {
            printMsg("INFO", "Using Java $2");
        }
    }
}

Unfortunately this doesn't solve the issue mentioned above.

ERROR: internal error in parser, try to reduce ARG_MAX

Version 2.0 triggers a "ERROR: internal error in parser, try to reduce ARG_MAX" message.
1.8 works fine on the very same data. I've found issue #7 but that is quite old.

My environment is Windows 7, JDK7. I specify two XML as input as well as a library name. Here is some debug output from perl. -debug for the tool didn't show anything new.

[exec] main::mergeTypes() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 881.
     [exec] main::mergeTypes() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 1354.
     [exec] main::findMethod() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 1490.
     [exec] main::getModules() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 50.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 55.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 56.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 57.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 58.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 59.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 60.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 61.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 62.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 63.
     [exec] main::loadModule() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 64.
     [exec] main::errMsg() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 147.
     [exec] main::errMsg() called too early to check prototype at c:\projects\japi-compliance\download\japi-compliance-checker line 158.
     [exec] Preparing, please wait ...
     [exec] main::getArgMax() called too early to check prototype at c:/projects/japi-compliance/download/modules/Internals/Utils.pm line 23.
     [exec] Use of uninitialized value $In::Opt{"OS"} in string eq at c:/projects/japi-compliance/download/modules/Internals/Utils.pm line 53.
     [exec] main::getBaseType() called too early to check prototype at c:/projects/japi-compliance/download/modules/Internals/TypeAttr.pm line 69.
     [exec] Use of uninitialized value $Java in hash element at c:/projects/japi-compliance/download/modules/Internals/SysFiles.pm line 150.
     [exec] Use of uninitialized value $Java in hash element at c:/projects/japi-compliance/download/modules/Internals/SysFiles.pm line 154.
     [exec] main::readArchive() called too early to check prototype at c:/projects/japi-compliance/download/modules/Internals/APIDump.pm line 179.
     [exec] main::registerType() called too early to check prototype at c:/projects/japi-compliance/download/modules/Internals/APIDump.pm line 830.
     [exec] Use of uninitialized value $In::Opt{"TargetLibraryName"} in concatenation (.) or string at c:/projects/japi-compliance/download/modules/Internals/Logging.pm line 78.
     [exec] Use of uninitialized value $Bin in hash element at c:/projects/japi-compliance/download/modules/Internals/SysFiles.pm line 150.
     [exec] Use of uninitialized value $Bin in hash element at c:/projects/japi-compliance/download/modules/Internals/SysFiles.pm line 154.
     [exec] Using Java 1.7.0_79
     [exec] Reading classes 5_35 ...
     [exec] Argument "" isn't numeric in numeric ne (!=) at c:/projects/japi-compliance/download/modules/Internals/Utils.pm line 110.
     [exec] Can't spawn "cmd.exe": No such file or directory at c:/projects/japi-compliance/download/modules/Internals/APIDump.pm line 324.
     [exec] ERROR: internal error in parser, try to reduce ARG_MAX

-classes-list <path> option is not working..

JAVA API compliance Checker (http://ispras.linuxbase.org/index.php/Java_API_Compliance_Checker) is a awesome tool. I love this tool. I tried to use -classes-list and found no success :(.

I stored all my classes on "classes.log".

Command I used:
./japi-compliance-checker -l "$LIB_NAME" -old $REF_BASE_LOCATION/version.xml -new $NEW_BASE_LOCATION/version.xml -source -v1 $REF_BUILD_VERSION -v2 $NEW_BUILD_VERSION -report-path report/$REPORT_NAME -classes-list classList.log

I tried on the following combinations (Listed on the bottom, 'Classes List:'), But no success :( I do not have much knowledge on Perl, however i reviewed the code and found,

Line Number (japi-compliance-checker): 1892

if($ClassListPath and defined $MethodInfo{$LibVersion}{$Method}
and not $ClassList_User{$MethodInfo{$LibVersion}{$Method}{"Class"}})
{ # user defined classes
return 0;
}

'$MethodInfo{$LibVersion}{$Method}{"Class"}' always return a integer like 654,867,191,1266,1475,1414,1268,1167, etc., not returning a class name (string). I feel there is a bug on this. Could you please confirm and guide me on this?

Classes List:

org/apache/log4j/LogManager.class
org/apache/log4j/Logger.class
org/apache/log4j/MDC.class
org/apache/log4j/NDC$DiagnosticContext.class
org/apache/log4j/NDC.class

org/apache/log4j/PatternLayout.class

org.apache.log4j.LogManager.class
org.apache.log4j.Logger.class
org.apache.log4j.MDC.class
org.apache.log4j.NDC$DiagnosticContext.class
org.apache.log4j.NDC.class

org.apache.log4j.PatternLayout.class

org.apache.log4j.LogManager
org.apache.log4j.Logger
org.apache.log4j.MDC
org.apache.log4j.NDC$DiagnosticContext
org.apache.log4j.NDC

org.apache.log4j.PatternLayout

org/apache/log4j/LogManager
org/apache/log4j/Logger
org/apache/log4j/MDC
org/apache/log4j/NDC$DiagnosticContext
org/apache/log4j/NDC

org/apache/log4j/PatternLayout

Thanks,
-Jeeva

Critical issue on Windows platform

readClasses gets paths without ending with .class (readArchive removes .class extension). On Windows javap returns an empty output and disassembling fails. I attached the logs for both cases bad.log and good.log. Dirty fix by patching readClasses with my $Input = join(".class ", @{$Paths});.
The biggest problem is that the tool gives false negative and reports 100% compatibility.

I'm using the latest version 1.7.

Can't locate Data/Dumper.pm in @INC

Can't locate Data/Dumper.pm in @inc (@inc contains: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/bin/japi-compliance-checker line 45.

Java 8 default interface methods not detected

I came across this problem recently...

API v1 has:

  • interface FaceA

API v2 introduces:

  • interface FaceB with method do()
  • interface FaceA extends FaceB and adds default implementation of do()

This should pose no compatibility risk because anyone implementing FaceA in their apps will still be able to run his with API v2 thanks to default implementation.

To give a real background I am talking about Java EE CDI spec...

This should be perfectly fine compatibility-wise so I think it is a glitch in the script?

-client CLIENT.jar then met ERROR: can't find "jar" command

JDK version: Java 1.7.0_79
Perl version: v5.18.2
OS: Mac OS 10.10.4
japi-compliance-checker version: latest

Issue I met:

japi-compliance-checker -lib mylib -old V1.xml -new V2.xml
This one works fine, the report can be generated.

But when append -client like this:
japi-compliance-checker -lib mylib -old V1.xml -new V2.xml -client testClient.jar

then met error message:
ERROR: can't find "jar" command

PS: "jar" command works fine in my command window when I execute it.

Anyone met this issue?

Include options in report

It would be nice if the report had another tab that show the options used to create the report.

When I use this tool I create two xml files that include and exclude packages. It would be nice if the report showed these xml files so that I could see what packages were considered to produce the report. Also I am using the new -skip-deprecated option, it would be nice to if the report showed that this option was specified.

This context would be useful when a user shares a report with others, so they can easily understand what options were used to produce the report. It would also be useful for historical purposes. If I go back and look at an old report, I may not remember what options I used to produce that report.

Changed methods

How can I get the changed methods between two versions of jars.

False positive source compatibility error with varargs

I noticed an issue where it claims something isn't source compatible when it actually is.

public int getValue() {...}  

public int getValue(Object... objects){ ... }

This change is binary incompatible, but it should be source compatible since you can still invoke it with no arguments.

False reports of removed methods when extending class with generic parameters

If we have this before:

class A {
  void foo();
}

And then the new version has:

class A extends B<String> {}
class B<T> {
  void foo();
}

Then the compliance checker falsely reports that foo has been removed. I think this might be because it is trying to find the methods of a class called B<String> rather than simply B so it gets back an empty set.

A similar bug affects this case:

interface I {}
class A implements I {}

When it is changed to:

interface I {}
class A extends B<String> {}
class B<T> implements I {}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.