Skip to content

[Xamarin.Android.Tools.Bytecode] Ignore synthetic ctor params #1091

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 30, 2023

Conversation

jonpryor
Copy link
Contributor

Fixes: #1090

Attempting to parse TensorFlow 1.13.1 with a Debug build of class-parse results in an assertion failure:

% curl -o tensorflow-android-1.13.1.aar https://repo1.maven.org/maven2/org/tensorflow/tensorflow-android/1.13.1/tensorflow-android-1.13.1.aar
% unzip tensorflow-android-1.13.1.aar classes.jar
% dotnet bin/Debug-net7.0/class-parse.dll classes.jar
Unexpected number of method parameters; expected 0, got 1
   at Xamarin.Android.Tools.Bytecode.MethodInfo.UpdateParametersFromMethodParametersAttribute(ParameterInfo[] parameters)
   at Xamarin.Android.Tools.Bytecode.MethodInfo.GetParameters()
   at Xamarin.Android.Tools.Bytecode.XmlClassDeclarationBuilder.GetMethodParameters(MethodInfo method)+MoveNext()
   at System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
   at System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
   at Xamarin.Android.Tools.Bytecode.XmlClassDeclarationBuilder.GetMethod(String element, String name, MethodInfo method, String returns)
   at Xamarin.Android.Tools.Bytecode.XmlClassDeclarationBuilder.<GetConstructors>b__23_2(MethodInfo c)

Note: this will only happen for Debug builds of class-parse, which we do not ship. Thus, this will only happen if you are using a local build of xamarin/Java.Interop.

The assertion occurs when processing the constructor for org/tensorflow/Session$Runner$Reference.class, which is a non-static inner class:

% unzip classes.jar 'org/tensorflow/Session$Runner$Reference.class'
% dotnet bin/Debug-net7.0/class-parse.dll --dump 'org/tensorflow/Session$Runner$Reference.class'
…
Methods Count: 2
	0: <init> (Lorg/tensorflow/Session$Runner;)V Public
		Code(60, Unknown[LineNumberTable](30), LocalVariableTableAttribute(LocalVariableTableEntry(Name='this', Descriptor='Lorg/tensorflow/Session$Runner$Reference;', StartPC=0, Index=0)), Xamarin.Android.Tools.Bytecode.StackMapTableAttribute)
		MethodParametersAttribute(MethodParameterInfo(Name='this$1', AccessFlags=Final, Synthetic))

Note the MethodParameterInfo.AccessFlags value for the parameter: AccessFlags=Final, Synthetic. This differs from the Final, Mandated value that is checked for by
MethodInfo.UpdateParametersFromMethodParametersAttribute():

var OuterThis = MethodParameterAccessFlags.Final | MethodParameterAccessFlags.Mandated;
// …
while (startIndex < pinfo.Count &&
    (pinfo [startIndex].AccessFlags & OuterThis) == OuterThis) {
  startIndex++;
}

Because the parameter is Final, Synthetic and not Final, Mandated, the parameter is not skipped, which results in the assertion message expected 0, got 1.

@jonpryor does not know how or why Final, Synthetic is being used by Session$Runner$Reference.class, and is unable to reproduce this particular Java bytecode output with the JDK 1.8 and JDK 11 compilers.

Update MethodInfo.UpdateParametersFromMethodParametersAttribute() to also skip Final, Synthetic parameters. This allows Session$Runner$Reference.class to be processed without assertions:

% dotnet bin/Debug-net7.0/class-parse.dll classes.jar
# no errors

Additionally, update the assertion message so that it includes the declaring class name, method name, and method descriptor.

Fixes: dotnet#1090

Attempting to parse [TensorFlow 1.13.1][0] with a Debug build of
`class-parse` results in an assertion failure:

	% curl -o tensorflow-android-1.13.1.aar https://repo1.maven.org/maven2/org/tensorflow/tensorflow-android/1.13.1/tensorflow-android-1.13.1.aar
	% unzip tensorflow-android-1.13.1.aar classes.jar
	% dotnet bin/Debug-net7.0/class-parse.dll classes.jar
	Unexpected number of method parameters; expected 0, got 1
	   at Xamarin.Android.Tools.Bytecode.MethodInfo.UpdateParametersFromMethodParametersAttribute(ParameterInfo[] parameters)
	   at Xamarin.Android.Tools.Bytecode.MethodInfo.GetParameters()
	   at Xamarin.Android.Tools.Bytecode.XmlClassDeclarationBuilder.GetMethodParameters(MethodInfo method)+MoveNext()
	   at System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
	   at System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
	   at Xamarin.Android.Tools.Bytecode.XmlClassDeclarationBuilder.GetMethod(String element, String name, MethodInfo method, String returns)
	   at Xamarin.Android.Tools.Bytecode.XmlClassDeclarationBuilder.<GetConstructors>b__23_2(MethodInfo c)

Note: this will only happen for Debug builds of `class-parse`, which
we do not ship.  Thus, this will only happen if you are using a local
build of xamarin/Java.Interop.

The assertion occurs when processing the constructor for
`org/tensorflow/Session$Runner$Reference.class`, which is a non-static
inner class:

	% unzip classes.jar 'org/tensorflow/Session$Runner$Reference.class'
	% dotnet bin/Debug-net7.0/class-parse.dll --dump 'org/tensorflow/Session$Runner$Reference.class'
	…
	Methods Count: 2
		0: <init> (Lorg/tensorflow/Session$Runner;)V Public
			Code(60, Unknown[LineNumberTable](30), LocalVariableTableAttribute(LocalVariableTableEntry(Name='this', Descriptor='Lorg/tensorflow/Session$Runner$Reference;', StartPC=0, Index=0)), Xamarin.Android.Tools.Bytecode.StackMapTableAttribute)
			MethodParametersAttribute(MethodParameterInfo(Name='this$1', AccessFlags=Final, Synthetic))

Note the `MethodParameterInfo.AccessFlags` value for the parameter:
`AccessFlags=Final, Synthetic`.  This differs from the
`Final, Mandated` value that is checked for by
`MethodInfo.UpdateParametersFromMethodParametersAttribute()`:

	var OuterThis = MethodParameterAccessFlags.Final | MethodParameterAccessFlags.Mandated;
	// …
	while (startIndex < pinfo.Count &&
	    (pinfo [startIndex].AccessFlags & OuterThis) == OuterThis) {
	  startIndex++;
	}

Because the parameter is `Final, Synthetic` and not `Final, Mandated`,
the parameter is *not* skipped, which results in the assertion message
`expected 0, got 1`.

@jonpryor does not know how or why `Final, Synthetic` is being used
by `Session$Runner$Reference.class`, and is unable to reproduce this
particular Java bytecode output with the JDK 1.8 and JDK 11 compilers.

Update `MethodInfo.UpdateParametersFromMethodParametersAttribute()`
to also skip `Final, Synthetic` parameters.  This allows
`Session$Runner$Reference.class` to be processed without assertions:

	% dotnet bin/Debug-net7.0/class-parse.dll classes.jar
	# no errors

Additionally, update the assertion message so that it includes the
declaring class name, method name, and method descriptor.

[0]: https://mvnrepository.com/artifact/org.tensorflow/tensorflow-android/1.13.1
@jonpryor jonpryor merged commit 0355acf into dotnet:main Mar 30, 2023
jonpryor pushed a commit to dotnet/android that referenced this pull request Mar 31, 2023
Fixes: dotnet/java-interop#1090

Changes: dotnet/java-interop@53bfb4a...0355acf

  * dotnet/java-interop@0355acf8: [Xamarin.Android.Tools.Bytecode] Ignore synthetic ctor params (dotnet/java-interop#1091)
  * dotnet/java-interop@909239d4: [generator] Add support for peerConstructorPartialMethod (dotnet/java-interop#1087)
  * dotnet/java-interop@8f3fe625: [generator] Fix an NRE when cloning a method with generic arguments (dotnet/java-interop#1089)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
@github-actions github-actions bot locked and limited conversation to collaborators Apr 12, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Assert matching method parameters in class-parse
2 participants