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 ...
Status: RESOLVED NORESPONSE
Alias: None
Product: Android
Classification: Xamarin
Component: Bindings (show other bugs)
Version: 6.1.0 (C7)
Hardware: PC Mac OS
: --- normal
Target Milestone: ---
Assignee: Atsushi Eno
URL:
Depends on:
Blocks:
 
Reported: 2016-07-05 19:30 UTC by James Athey
Modified: 2017-10-04 15:21 UTC (History)
3 users (show)

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


Attachments

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:

https://github.com/xamarin/jar2xml/blob/106fe9f74a75ce67ee58fc69e5545fef1189508b/JavaArchive.java#L77
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!

Note You need to log in before you can comment on or make changes to this bug.