Find file
311 lines (227 sloc) 11.4 KB
jar2xml is a tool to extract API information from a java archive
and associated documentation. The information is stored in XML format.
* Prerequisites
- mono (to run build tools)
- xmllint (for doc scraping)
- xmlstarlet (ditto)
Also it uses ASM (included in the sources)
* Tools
- jar2xml : the main converter to generate the primary target xmls.
- scraper.exe : annotation doc scraper to generate annotations/*.xml.
scraper-*.sh : shells used for scraper input. They are piped.
* <del>Easy</del> comparison
There are two levels of comparisons.
DLL: gui-compare in mono-tools is your friend. Compare new one against
old assembly of the corresponding API profile.
XML: It is now implemented as "make test-8" as well as "make test-13"
See Makefile for details. Things are not really simple to explain shortly.
$ java -jar jar2xml.jar --jar=/home/atsushi/android-sdk-linux_x86/platforms/android-8/android.jar --out=_8.xml --docpath=/home/atsushi/android-sdk-linux_x86/docs/reference
$ mono-xmltool --prettyprint 8.xml > 8_.xml
$ xmlstarlet c14n 8_.xml > 8.xml
$ mono-xmltool --prettyprint _8.xml > _8_.xml
$ xmlstarlet c14n _8_.xml > _8.xml
$ diff -u 8.xml _8.xml
* Difference from AOSP API XML
- Type parameters on Class and Method are now explicitly written as:
<typeParameters> <!-- if any -->
<typeParameter name="...">
<genericConstraints> <!-- if any -->
<genericConstraint type="..."></genericConstraint>
see e.g. android.accounts.AccountManagerCallback<V>
There are some cases that we dare output type parameters embedded
into type name (basically those in XML attributes):
- genericConstraint/@type (see above)
- exception/@type (it would hardly happen though)
These are temporarily disabled and will be back when we really move
to the new generic design.
- class/@extends
- implements/@name
- field/@type
** Postponed
- : missing in jar2xml output.
Disappeared in the shade of Hashtable.put().
-> workarounded by explicitly excluding the case (hardcoded in jar2xml!)
This issue should rather get fixed by improving overrload resolution
in XML level i.e. change XML format to include *any* overloaded methods
that AOSP XML does not do.
- and .ctor() : types differ
- generic list
- Now there are some abstract methods that somehow lacked in AOSP XML
and it uncovered issues regarding overriden methods. While those overriden
methods are sometimes "final", which should be "sealed", they are not
marked as sealed. And we cannot mark them as sealed right now since
those methods are *overriden* in *Invoker classes.
e.g. java.nio.Buffer.arrayOffset() and those overriden methods in *Buffer.
- android.hardware.SensorManager.GRAVITY_DEATH_STAR_I always returns 0
- while reference and AOSP indicates value, it returns 0 on reflection,
asm or even on ASUS Transformer.
- android.test.MoreAsserts.assertEquals(Set<?>, Set<?>).
They are just XML difference between <?> (wrong) and <? extends Object>
(correct), which affected doc scraping for parameter name retrieval.
- java.util.Calendar AllStyles, Long and Short are now properties, but
they should be actually enums. The thing is, they are *missing* in AOSP
XML so they had weren't converted to enums by our generator stuff.
- android.util.Pair : ThresholdClass and ThreasholdType are extraneous.
They are not in jar2xml output either, maybe added by api fixup stage.
(First and Second are looking as extra, but they were rather missing)
** things changes are maybe preferred
*** int->enum
- Android.App.DownloadManager
- Android.Appwidget.AppWidgetManager
- Android.Bluetooth.BluetoothA2dp
- Android.Bluetooth.BluetoothHeadset
- Android.Content.PM.PackageManager
- Android.Content.Res.Configuration
- Android.Database.Sqlite.SQLiteDatabase
- Android.Graphics.PowerDuff.Mode
- Android.Media.AudioManager.ScoAudioState*
- Android.OS.BatteryManager
- Android.Views.InputDevice
- Android.Views.View.Measured*
- Android.Views.Window.Progress*
- Android.Views.Window.WindowManagerLayoutParams
- Android.Views.View.SystemUiVisibilityChangeEventArgs has int Visibility
which should be StatusBarVisibility.
- Android.Widget.OnScrollListenerConsts
*** methods->properties
- Android.App.Admin.DevicePolicyManager: there are lots of GetPassword*() and
SetPassword*() methods which we might be able to change to indexers.
* Notes (that you don't have to read)
** API difference between android.jar and J2SE
These API differences could be problematic when we reflect java system types (reflection limitation).
- is synchronized in android
and not in J2SE.
-> in jar2xml, it is manually fixed.
** AOSP XML issues
Lots of missing pieces:
** Notes on Annotations
Annotation such as java.lang.Deprecated do not seem to exist
in android.jar. That includes, types themselves.
java.lang.annotation types suffer from this.
I find it almost desparate and the only solution I couold think of was
to build AOSP android.jar or some equivalence that does *not* strip
those annotations off, *for each platform version*.
That sounds so time-eater.
The AOSP API document is generated as out/target/common/obj/PACKAGING/android_jar_intermediaries/public_api.xml (at that state there still must be annotations, or this xml should not contain annotation information at all).
out/target/common/obj/JAVA_LIBRARIES/framework_intermediaries and
contains debug jars that still seem to hold annotations.
development/tools/apkcheck/README.txt might be of interest too.
This is from the latest AOSP build (as of Aug.17, 2011). I'm not sure
if this applies to older versions.
On the other hand, I noticed that Annotation types are very easy to fill;
they have almost fixed members (from java.lang.Object). So I rather
think they can be manually filled (or if we want to be puritan, scrape
"Known Indirect Subclasses" from java/lang/annotation/Annotation.html).
Annotations are:
** Old Notes on Annotations
Current implementation uses java.lang.reflect API to get member
annotations, but it won't work as expected.
I found that .class files in android.jar are stripped off field
annotations. For example,
should be annotated with @Deprecated, but it isn't.
On the other hand, class annotations are alive.
(e.g. java/security/Certificate.class)
I guess is that AOSP uses proguard which strips member annotations.
The reason why we can somehow retrieve @Deprecated on
HttpURLConnection#HTTP_SERVER_ERROR by jar2xml is likely that
URLClassLoader.getClass() actually does not load java.* classes from
the jar contents but just returns the runtime one (such as openjdk).
Javassist.Loader javadoc explains its limitation on loading java.*
/ javax.* classes. [*1]
(So, it is not even about "runtime visible/invisible annotations".
I tried to read android.jar classes using ASM ClassReader [*2] and
it couldn't find any annotations on FieldNode (and from what I read
from asm sources, I believe it is by no means bug in ASM).
I have added separate doc scraper, which uses xmllint (to xmlize html docs)
and xmlstarlet (for convenient XPath query). Run "make annotations/13.xml"
for instance (should be available to all versions, I'm just lazy to hack
makefiles before confirming that it's all good).
** Notes on per-version doc scraping
We used to scrape only reference for the latest API which was problematic.
Now we have version-aware scraper and resolved the issue described below.
Doc scraper still misses some parameter names
e.g. android.text.method.ScrollingMovementMethod.onKeyUp()
This matters when api-fixup is involved (it matches nodes by parameter
names and then it dismisses the target nodes!).
Actually this is not going to be very good; there are some methods
that are removed in the latest API (the example method above is exactly
the case). We'll have to sort out some alternative approach.
A possible approach is to checkout API docs for *every* version (from
** Byte code engineering
Now we use ASM to solve the issues below:
- Some fields were incorrectly marked as constant. For example,
android.os.Build.TIME is not a constant, but since the field.getLong()
returns 0, it is set as 0 (and it does not return null for get()). has the same problem, but it is worse;
it returns non-zero value so we cannot depend on the value.
Solution ideas: scrape constant values, or use ASM.
- Constant values for "protected" fields need to be retrieved, but Java reflection API throws IllegalAccessException for such attempt.
This likely has to be resolved by bytecode engineering (such as ASM).
** Issues regarding stripped non-public class (resolved)
- java.lang.AbstractStringBuilder exposes an issue that
interface members on non-public types are returned by
class#getDeclaredMethods() while they are *not* declared.
Those methods (or those AbstractStringBuilder methods) are excluded by
checking special modifier 0x1000 (4096).
Also this involves check for derived methods (many overriden methods are
excluded, but this brings another check to *not* exclude methods when
the corresponding base methods are excluded).
** Method override resolution
- Do not skip certain overriden methods. This in gives
equivalent output to AOSP xml, but it's not good:
if (base_method != null) {
int base_mods = base_method.getModifiers ();
if (!Modifier.isAbstract (base_mods) && (Modifier.isPublic (mmods) == Modifier.isPublic (base_mods)))
This causes GridView.setAdapter() ignored and thus fails to generate
valid property. It hides overriden methods.
I simply commented out, then a bunch of hidden overriden methods
appeared. And since we don't handle int->enum conversions on those
methods, they simply fail to compile. Maybe fixing above to match
existing format is a good-enough compromization.
Another notable thing is that AbsListView.setAdapter() does not
exist in api-4.xml. It is likely because abstract methods are
ignored (it is abstract, though that fact does not appear on
android javadoc).
android.view.MotionEvent.getSource() is also missing.