Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions build-tools/scripts/RunNUnitTests.targets
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,6 @@
</ItemGroup>
<Target Name="RunTests"
Outputs="$(_TopDir)\TestResult-%(_TestAssembly.Filename).xml">
<ItemGroup>
<_JavaInteropNativeLibrary Include="$(_TopDir)\bin\$(Configuration)\libjava-interop.*" />
</ItemGroup>
<Copy
SourceFiles="@(_JavaInteropNativeLibrary)"
DestinationFolder="$(_TopDir)\bin\Test$(Configuration)"
SkipUnchangedFiles="True"
/>
<SetEnvironmentVariable Name="ANDROID_SDK_PATH" Value="$(AndroidSdkDirectory)" Condition=" '$(AndroidSdkDirectory)' != '' " />
<SetEnvironmentVariable Name="MONO_TRACE_LISTENER" Value="Console.Out" />
<SetEnvironmentVariable Name="JAVA_INTEROP_GREF_LOG" Value="bin\Test$(Configuration)\g-%(_TestAssembly.Filename).txt" />
Expand Down
9 changes: 6 additions & 3 deletions src/Java.Interop/Java.Interop/JavaProxyObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ sealed class JavaProxyObject : JavaObject, IEquatable<JavaProxyObject>
[JniAddNativeMethodRegistrationAttribute]
static void RegisterNativeMembers (JniNativeMethodRegistrationArguments args)
{
args.Registrations.Add (new JniNativeMethodRegistration ("equals", "(Ljava/lang/Object;)Z", (Func<IntPtr, IntPtr, IntPtr, bool>)Equals));
args.Registrations.Add (new JniNativeMethodRegistration ("hashCode", "()I", (Func<IntPtr, IntPtr, int>)GetHashCode));
args.Registrations.Add (new JniNativeMethodRegistration ("toString", "()Ljava/lang/String;", (Func<IntPtr, IntPtr, IntPtr>)ToString));
args.Registrations.Add (new JniNativeMethodRegistration ("equals", "(Ljava/lang/Object;)Z", (EqualsMarshalMethod)Equals));
args.Registrations.Add (new JniNativeMethodRegistration ("hashCode", "()I", (GetHashCodeMarshalMethod)GetHashCode));
args.Registrations.Add (new JniNativeMethodRegistration ("toString", "()Ljava/lang/String;", (ToStringMarshalMethod)ToString));
}

public override JniPeerMembers JniPeerMembers {
Expand Down Expand Up @@ -72,6 +72,7 @@ public override bool Equals (object? obj)
}

// TODO: Keep in sync with the code generated by ExportedMemberBuilder
delegate bool EqualsMarshalMethod (IntPtr jnienv, IntPtr n_self, IntPtr n_value);
static bool Equals (IntPtr jnienv, IntPtr n_self, IntPtr n_value)
{
var envp = new JniTransition (jnienv);
Expand All @@ -91,6 +92,7 @@ static bool Equals (IntPtr jnienv, IntPtr n_self, IntPtr n_value)
}

// TODO: Keep in sync with the code generated by ExportedMemberBuilder
delegate int GetHashCodeMarshalMethod (IntPtr jnienv, IntPtr n_self);
static int GetHashCode (IntPtr jnienv, IntPtr n_self)
{
var envp = new JniTransition (jnienv);
Expand All @@ -107,6 +109,7 @@ static int GetHashCode (IntPtr jnienv, IntPtr n_self)
}
}

delegate IntPtr ToStringMarshalMethod (IntPtr jnienv, IntPtr n_self);
static IntPtr ToString (IntPtr jnienv, IntPtr n_self)
{
var envp = new JniTransition (jnienv);
Expand Down
51 changes: 33 additions & 18 deletions src/Java.Interop/Java.Interop/JniEnvironment.Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,37 @@ public static unsafe JniObjectReference FindClass (string classname)
}

NativeMethods.java_interop_jnienv_exception_clear (info.EnvironmentPointer);
var e = new JniObjectReference (thrown, JniObjectReferenceType.Local);
LogCreateLocalRef (e);

var findClassThrown = new JniObjectReference (thrown, JniObjectReferenceType.Local);
LogCreateLocalRef (findClassThrown);
var pendingException = info.Runtime.GetExceptionForThrowable (ref findClassThrown, JniObjectReferenceOptions.CopyAndDispose);

if (info.Runtime.ClassLoader_LoadClass != null) {
var java = info.ToJavaName (classname);
var __args = stackalloc JniArgumentValue [1];
__args [0] = new JniArgumentValue (java);

IntPtr ignoreThrown;
c = NativeMethods.java_interop_jnienv_call_object_method_a (info.EnvironmentPointer, out ignoreThrown, info.Runtime.ClassLoader.Handle, info.Runtime.ClassLoader_LoadClass.ID, (IntPtr) __args);
c = NativeMethods.java_interop_jnienv_call_object_method_a (info.EnvironmentPointer, out thrown, info.Runtime.ClassLoader.Handle, info.Runtime.ClassLoader_LoadClass.ID, (IntPtr) __args);
JniObjectReference.Dispose (ref java);
if (ignoreThrown == IntPtr.Zero) {
JniObjectReference.Dispose (ref e);
if (thrown == IntPtr.Zero) {
(pendingException as IJavaPeerable)?.Dispose ();
var r = new JniObjectReference (c, JniObjectReferenceType.Local);
JniEnvironment.LogCreateLocalRef (r);
return r;
}
NativeMethods.java_interop_jnienv_exception_clear (info.EnvironmentPointer);
NativeMethods.java_interop_jnienv_delete_local_ref (info.EnvironmentPointer, ignoreThrown);

if (pendingException != null) {
NativeMethods.java_interop_jnienv_delete_local_ref (info.EnvironmentPointer, thrown);
}
else {
var loadClassThrown = new JniObjectReference (thrown, JniObjectReferenceType.Local);
LogCreateLocalRef (loadClassThrown);
pendingException = info.Runtime.GetExceptionForThrowable (ref loadClassThrown, JniObjectReferenceOptions.CopyAndDispose);
}
}

throw info.Runtime.GetExceptionForThrowable (ref e, JniObjectReferenceOptions.CopyAndDispose)!;
throw pendingException!;
#endif // !FEATURE_JNIENVIRONMENT_JI_PINVOKES
#if FEATURE_JNIOBJECTREFERENCE_SAFEHANDLES
var c = info.Invoker.FindClass (info.EnvironmentPointer, classname);
Expand All @@ -80,25 +88,32 @@ public static unsafe JniObjectReference FindClass (string classname)
return new JniObjectReference (c, JniObjectReferenceType.Local);
}
info.Invoker.ExceptionClear (info.EnvironmentPointer);
LogCreateLocalRef (thrown);
var findClassThrown = new JniObjectReference (thrown, JniObjectReferenceType.Local);
LogCreateLocalRef (findClassThrown);
var pendingException = info.Runtime.GetExceptionForThrowable (ref findClassThrown, JniObjectReferenceOptions.CopyAndDispose);

var java = info.ToJavaName (classname);
var __args = stackalloc JniArgumentValue [1];
__args [0] = new JniArgumentValue (java);

c = info.Invoker.CallObjectMethodA (info.EnvironmentPointer, info.Runtime.ClassLoader.SafeHandle, info.Runtime.ClassLoader_LoadClass.ID, __args);
c = info.Invoker.CallObjectMethodA (info.EnvironmentPointer, info.Runtime.ClassLoader.SafeHandle, info.Runtime.ClassLoader_LoadClass.ID, __args);
JniObjectReference.Dispose (ref java);
var ignoreThrown = info.Invoker.ExceptionOccurred (info.EnvironmentPointer);
thrown = info.Invoker.ExceptionOccurred (info.EnvironmentPointer);
if (ignoreThrown.IsInvalid) {
thrown.Dispose ();
JniEnvironment.LogCreateLocalRef (c);
return new JniObjectReference (c, JniObjectReferenceType.Local);
(pendingException as IJavaPeerable)?.Dispose ();
var r = new JniObjectReference (c, JniObjectReferenceType.Local);
JniEnvironment.LogCreateLocalRef (r);
return r;
}
info.Invoker.ExceptionClear (info.EnvironmentPointer);
LogCreateLocalRef (ignoreThrown);
ignoreThrown.Dispose ();
var e = new JniObjectReference (thrown, JniObjectReferenceType.Local);
throw info.Runtime.GetExceptionForThrowable (ref e, JniObjectReferenceOptions.CopyAndDispose);
if (pendingException != null) {
thrown.Dispose ();
throw pendingException;
}
var loadClassThrown = new JniObjectReference (thrown, JniObjectReferenceType.Local);
LogCreateLocalRef (loadClassThrown);
pendingException = info.Runtime.GetExceptionForThrowable (ref loadClassThrown, JniObjectReferenceOptions.CopyAndDispose);
throw pendingException!;
#endif // !FEATURE_JNIOBJECTREFERENCE_SAFEHANDLES
}

Expand Down
27 changes: 13 additions & 14 deletions src/Java.Interop/Java.Interop/ManagedPeer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,6 @@ namespace Java.Interop {
[JniTypeSignature (JniTypeName)]
/* static */ sealed class ManagedPeer : JavaObject {

delegate void ConstructDelegate (IntPtr jnienv,
IntPtr klass,
IntPtr n_self,
IntPtr n_assemblyQualifiedName,
IntPtr n_constructorSignature,
IntPtr n_constructorArguments);
delegate void RegisterDelegate (IntPtr jnienv,
IntPtr klass,
IntPtr n_nativeClass,
IntPtr n_assemblyQualifiedName,
IntPtr n_methods);

internal const string JniTypeName = "com/xamarin/java_interop/ManagedPeer";


Expand All @@ -37,11 +25,11 @@ static ManagedPeer ()
new JniNativeMethodRegistration (
"construct",
ConstructSignature,
(ConstructDelegate) Construct),
(ConstructMarshalMethod) Construct),
new JniNativeMethodRegistration (
"registerNativeMembers",
RegisterNativeMembersSignature,
(RegisterDelegate) RegisterNativeMembers)
(RegisterMarshalMethod) RegisterNativeMembers)
);
}

Expand All @@ -62,6 +50,12 @@ public override JniPeerMembers JniPeerMembers {
const string ConstructSignature = "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V";

// TODO: Keep in sync with the code generated by ExportedMemberBuilder
delegate void ConstructMarshalMethod (IntPtr jnienv,
IntPtr klass,
IntPtr n_self,
IntPtr n_assemblyQualifiedName,
IntPtr n_constructorSignature,
IntPtr n_constructorArguments);
static void Construct (
IntPtr jnienv,
IntPtr klass,
Expand Down Expand Up @@ -183,6 +177,11 @@ static Type[] GetParameterTypes (string? signature)

const string RegisterNativeMembersSignature = "(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)V";

delegate void RegisterMarshalMethod (IntPtr jnienv,
IntPtr klass,
IntPtr n_nativeClass,
IntPtr n_assemblyQualifiedName,
IntPtr n_methods);
static void RegisterNativeMembers (
IntPtr jnienv,
IntPtr klass,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
extends java.lang.Object
implements GCUserPeerable
{
static final String assemblyQualifiedName = "Java.Interop.JavaProxyObject, Java.Interop, Version=0.1.0.0, Culture=neutral, PublicKeyToken=null";
static final String assemblyQualifiedName = "Java.Interop.JavaProxyObject, Java.Interop";
static {
com.xamarin.java_interop.ManagedPeer.registerNativeMembers (
JavaProxyObject.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
extends java.lang.Error
implements GCUserPeerable
{
static final String assemblyQualifiedName = "Java.Interop.JavaProxyThrowable, Java.Interop, Version=0.1.0.0, Culture=neutral, PublicKeyToken=null";
static final String assemblyQualifiedName = "Java.Interop.JavaProxyThrowable, Java.Interop";
static {
com.xamarin.java_interop.ManagedPeer.registerNativeMembers (
JavaProxyThrowable.class,
Expand Down
52 changes: 52 additions & 0 deletions src/Java.Runtime.Environment/Java.Interop/JreRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;

Expand Down Expand Up @@ -44,6 +45,10 @@ public JreRuntimeOptions ()
ValueManager = ValueManager ?? new MonoRuntimeValueManager ();
ObjectReferenceManager = ObjectReferenceManager ?? new MonoRuntimeObjectReferenceManager ();
}
else {
ValueManager = ValueManager ?? new DummyValueManager ();
ObjectReferenceManager = ObjectReferenceManager ?? new DummyObjectReferenceManager ();
}
}

public JreRuntimeOptions AddOption (string option)
Expand Down Expand Up @@ -161,5 +166,52 @@ partial class NativeMethods {
[DllImport (JavaInteropLib, CharSet=CharSet.Ansi, CallingConvention=CallingConvention.Cdecl)]
internal static extern int java_interop_jvm_create (out IntPtr javavm, out IntPtr jnienv, ref JavaVMInitArgs args);
}

class DummyValueManager : JniRuntime.JniValueManager {

public override void WaitForGCBridgeProcessing ()
{
}

public override void CollectPeers ()
{
}

public override void AddPeer (IJavaPeerable reference)
{
}

public override void RemovePeer (IJavaPeerable reference)
{
}

public override void FinalizePeer (IJavaPeerable reference)
{
}

public override List<JniSurfacedPeerInfo> GetSurfacedPeers ()
{
return null;
}

public override IJavaPeerable PeekPeer (global::Java.Interop.JniObjectReference reference)
{
return null;
}

public override void ActivatePeer (IJavaPeerable self, JniObjectReference reference, ConstructorInfo cinfo, object [] argumentValues)
{
}
}

class DummyObjectReferenceManager : JniRuntime.JniObjectReferenceManager {
public override int GlobalReferenceCount {
get {return 0;}
}

public override int WeakGlobalReferenceCount {
get {return 0;}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

<ItemGroup>
<ProjectReference Include="..\Java.Interop\Java.Interop.csproj" />
<ProjectReference Include="..\..\src\java-interop\java-interop.csproj" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/java-interop/java-interop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
</ItemDefinitionGroup>

<ItemGroup>
<ClCompile Include="jni.c" />
<ClCompile Include="$(IntermediateOutputPath)jni.c" />
<ClCompile Include="java-interop.cc" />
<ClCompile Include="java-interop-dlfcn.cc" />
<ClCompile Include="java-interop-jvm.cc" />
Expand Down
21 changes: 16 additions & 5 deletions src/java-interop/java-interop.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,33 @@
<Project>
<Target Name="BuildJni_c"
Inputs="$(_JNIEnvGenPath)"
Outputs="jni.c">
Outputs="$(IntermediateOutputPath)jni.c">
<MakeDir Directories="$(OutputPath)" />
<Exec Command="$(_RunJNIEnvGen) jni.g.cs jni.c" />
<Exec Command="$(_RunJNIEnvGen) $(IntermediateOutputPath)jni.g.cs $(IntermediateOutputPath)jni.c" />
</Target>

<PropertyGroup>
<_MacLib>$(OutputPath)/lib$(OutputName).dylib</_MacLib>
<_UnixLib>$(OutputPath)/lib$(OutputName).so</_UnixLib>
</PropertyGroup>

<ItemGroup Condition=" '$(OS)' != 'Windows_NT' And Exists ('/Library/Frameworks/') ">
<None Include="$(_MacLib)">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup Condition=" '$(OS)' != 'Windows_NT' And !Exists ('/Library/Frameworks/') ">
<None Include="$(_UnixLib)">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>$([MSBuild]::Unescape($(DefineSymbols.Replace(' ', ';'))))</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$([MSBuild]::Unescape($(_MonoIncludePath)));$([MSBuild]::Unescape($(_JdkIncludePath)))</AdditionalIncludeDirectories>
<Obj Condition=" '$(OS)' != 'Windows_NT' ">obj/$(Configuration)/%(Filename).o</Obj>
<Obj Condition=" '$(OS)' != 'Windows_NT' ">$(IntermediateOutputPath)/%(Filename).o</Obj>
</ClCompile>
</ItemDefinitionGroup>

Expand All @@ -25,7 +37,7 @@
DependsOnTargets="BuildJni_c"
Inputs="@(ClCompile);@(ClInclude)"
Outputs="%(ClCompile.Obj)">
<MakeDir Directories="obj\$(Configuration)" />
<MakeDir Directories="$(IntermediateOutputPath)" />
<ItemGroup>
<_Cl Include="@(ClCompile)">
<Compiler Condition=" '%(Extension)' == '.c' ">gcc -std=c99 -fPIC</Compiler>
Expand Down Expand Up @@ -86,7 +98,6 @@

<Target Name="Clean">
<RemoveDir Directories="obj" />
<Delete Files="jni.c" />
<Delete
Files="$(_MacLib);$(_UnixLib)"
Condition=" '$(OS)' != 'Windows_NT' "
Expand Down
2 changes: 1 addition & 1 deletion tests/Java.Interop-Tests/Java.Interop-Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
<IsPackable>false</IsPackable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class CallVirtualFromConstructorDerived : CallVirtualFromConstructorBase
[JniAddNativeMethodRegistrationAttribute]
static void RegisterNativeMembers (JniNativeMethodRegistrationArguments args)
{
args.Registrations.Add (new JniNativeMethodRegistration ("calledFromConstructor", "(I)V", (Action<IntPtr, IntPtr, int>)CalledFromConstructorHandler));
args.Registrations.Add (new JniNativeMethodRegistration ("calledFromConstructor", "(I)V", (CalledFromConstructorMarshalMethod)CalledFromConstructorHandler));
}

public override JniPeerMembers JniPeerMembers {
Expand Down Expand Up @@ -57,6 +57,7 @@ public static unsafe CallVirtualFromConstructorDerived NewInstance (int value)
return JniEnvironment.Runtime.ValueManager.GetValue<CallVirtualFromConstructorDerived> (ref o, JniObjectReferenceOptions.CopyAndDispose);
}

delegate void CalledFromConstructorMarshalMethod (IntPtr jnienv, IntPtr n_self, int value);
static void CalledFromConstructorHandler (IntPtr jnienv, IntPtr n_self, int value)
{
var envp = new JniTransition (jnienv);
Expand Down
Loading