Bug 42367 - private static inner classes in JAR get wrapped and exposed as nested public classes in C#
Summary: private static inner classes in JAR get wrapped and exposed as nested public ...
Alias: None
Product: Android
Classification: Xamarin
Component: Bindings ()
Version: 6.1.0 (C7)
Hardware: PC Mac OS
: --- normal
Target Milestone: ---
Assignee: Atsushi Eno
Depends on:
Reported: 2016-07-05 19:30 UTC by James Athey
Modified: 2017-10-04 15:21 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description James Athey 2016-07-05 19:30:23 UTC
jar2xml processes all .class files in the jar without checking their visibility. The resulting C# binding gets public APIs to access private static inner classes, violating encapsulation, bloating the wrapper, and increasing the library's public surface area.

For example, the following java source:

package com.example;

public class PublicClass {

  public PublicClass() {
    // ...

  private static PrivateStaticInnerClass {
    public PrivateStaticInnerClass() {
      // ...


Compiles to a JAR file with both a com/example/PublicClass.class file and a com/example/PublicClass$PrivateStaticInnerClass.class file. Unfortunately, JavaArchive.getPackages() assumes that all .class files should be wrapped. The relevant source is here:

Comment 1 James Athey 2016-07-06 18:32:10 UTC
On further review, it looks like jar2xml is _supposed_ to emit everything, whether it's private or not, and it's up to the generator to make the right call. So perhaps this bug is better defined as "the generator wraps classes even when the visibility attribute is empty".
Comment 2 Atsushi Eno 2016-08-15 06:29:02 UTC
This needs some practical experiment, but I believe this behavioral design has historical reason to dare to expose package private classes to the public (but that is also most likely going to be past issue now that we have different jar API parser than "jar2xml").

Changing this behavior likely brings generated API changes so I'm quite negative to "fix" this issue with jar2xml. It is possible that we can "fix" the behavior with the new class-parse API parser, but (rephrased) it needs some practical experiment.
Comment 3 Jonathan Pryor 2016-08-18 18:38:08 UTC
It's not possible to "fix" this behavior with class-parse either.

> it looks like jar2xml is _supposed_ to emit everything

That is correct.

Now, *why*? Because Java is "laxer" than C# in many areas. For example, inheriting a public type from a non-public type is valid in Java but not C#:

    package android.text;

    /* package */ class SpannableStringInternal {

    public class SpannableString extends SpannableStringInternal {

If all non-public types were excluded from the API description, then `SpannableStringInternal` wouldn't be present *at all*, which means we'd either be "missing" members declared in there, or we'd have to manually re-introduce those members. Neither option is good.

Thus, we generate the API description for *everything*, and let generator+metadata sort it out. (Metadata can be used to alter visibility of types.)

That said, I thought generator *did* skip private members and package-private members.

@James: Would you be able to create a repro where private members are bound automatically?
Comment 4 Jon Douglas [MSFT] 2017-10-04 15:21:09 UTC
Because we have not received a reply to our request for more information we are closing this issue. If you are still encountering this issue, please reopen the ticket with the requested information. Thanks!