Skip to content
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

[Java.Runtime.Environment] Partial support for .NET Core #804

Merged
merged 1 commit into from
Feb 23, 2021
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
1 change: 1 addition & 0 deletions build-tools/automation/azure-pipelines.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ variables:
DotNetCoreVersion: 3.1.300
HostedMacImage: macOS-10.15
HostedWinVS2019: Hosted Windows 2019 with VS2019
NetCoreTargetFrameworkPathSuffix: -netcoreapp3.1

jobs:
- job: windows_build
Expand Down
8 changes: 8 additions & 0 deletions build-tools/automation/templates/core-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,14 @@ steps:
arguments: bin/Test$(Build.Configuration)/Java.Interop-Tests.dll
continueOnError: true

- task: DotNetCoreCLI@2
displayName: 'Tests: Java.Interop'
condition: eq('${{ parameters.runNativeTests }}', 'true')
inputs:
command: test
arguments: bin/Test$(Build.Configuration)$(NetCoreTargetFrameworkPathSuffix)/Java.Interop-Tests.dll
continueOnError: true

- task: DotNetCoreCLI@2
displayName: 'Tests: Java.Interop.Dynamic'
condition: eq('${{ parameters.runNativeTests }}', 'true')
Expand Down
7 changes: 6 additions & 1 deletion src/Java.Interop.Export/Java.Interop/MarshalMemberBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,12 @@ static Expression GetRuntime ()
return Expression.Property (null, typeof (JniEnvironment), "Runtime");
}

static MethodInfo FormatterServices_GetUninitializedObject = Type.GetType ("System.Runtime.Serialization.FormatterServices", throwOnError: true)
static MethodInfo FormatterServices_GetUninitializedObject =
#if NETCOREAPP
typeof (System.Runtime.CompilerServices.RuntimeHelpers)
#else // !NETCOREAPP
typeof (System.Runtime.Serialization.FormatterServices)
#endif // NETCOREAPP
.GetRuntimeMethod ("GetUninitializedObject", new[]{typeof (Type)});
static MethodInfo IJavaPeerable_SetPeerReference = typeof (IJavaPeerable).GetRuntimeMethod ("SetPeerReference", new[]{typeof (JniObjectReference)});

Expand Down
18 changes: 18 additions & 0 deletions src/Java.Interop/Java.Interop/JniEnvironment.Types.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#nullable enable

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Text;

Expand Down Expand Up @@ -47,6 +48,12 @@ public static unsafe JniObjectReference FindClass (string classname)
return r;
}

// If the Java-side exception stack trace is *lost* a'la 89a5a229,
// change `false` to `true` and rebuild+re-run.
#if false
NativeMethods.java_interop_jnienv_exception_describe (info.EnvironmentPointer);
#endif

NativeMethods.java_interop_jnienv_exception_clear (info.EnvironmentPointer);

var findClassThrown = new JniObjectReference (thrown, JniObjectReferenceType.Local);
Expand Down Expand Up @@ -167,6 +174,17 @@ public static void RegisterNatives (JniObjectReference type, JniNativeMethodRegi

public static void RegisterNatives (JniObjectReference type, JniNativeMethodRegistration [] methods, int numMethods)
{
#if DEBUG && NETCOREAPP
foreach (var m in methods) {
if (m.Marshaler.GetType ().GenericTypeArguments.Length != 0) {
var method = m.Marshaler.Method;
Debug.WriteLine ($"JNIEnv::RegisterNatives() given a generic delegate type. .NET Core doesn't like this.");
Debug.WriteLine ($" Java: {m.Name}{m.Signature}");
Debug.WriteLine ($" Marshaler Type={m.Marshaler.GetType ().FullName} Method={method.DeclaringType.FullName}.{method.Name}");
}
}
#endif // DEBUG && NETCOREAPP

int r = _RegisterNatives (type, methods, numMethods);

if (r != 0) {
Expand Down
72 changes: 14 additions & 58 deletions src/Java.Runtime.Environment/Java.Interop/JreRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public class JreRuntimeOptions : JniRuntime.CreationOptions {

public Collection<string> ClassPath {get; private set;}

public TextWriter? JniGlobalReferenceLogWriter {get; set;}
public TextWriter? JniLocalReferenceLogWriter {get; set;}

public JreRuntimeOptions ()
{
JniVersion = JniVersion.v1_2;
Expand All @@ -39,16 +42,6 @@ public JreRuntimeOptions ()
Path.GetDirectoryName (typeof (JreRuntimeOptions).Assembly.Location),
"java-interop.jar"),
};

bool onMono = Type.GetType ("Mono.Runtime", throwOnError: false) != null;
if (onMono) {
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 @@ -87,12 +80,22 @@ static unsafe JreRuntimeOptions CreateJreVM (JreRuntimeOptions builder)
if (builder == null)
throw new ArgumentNullException ("builder");

bool onMono = Type.GetType ("Mono.Runtime", throwOnError: false) != null;
if (onMono) {
builder.ValueManager = builder.ValueManager ?? new MonoRuntimeValueManager ();
builder.ObjectReferenceManager = builder.ObjectReferenceManager ?? new MonoRuntimeObjectReferenceManager ();
}
else {
builder.ValueManager = builder.ValueManager ?? new ManagedValueManager ();
builder.ObjectReferenceManager = builder.ObjectReferenceManager ?? new ManagedObjectReferenceManager (builder.JniGlobalReferenceLogWriter, builder.JniLocalReferenceLogWriter);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. We don't have to create the managers before creating the VM. I like that change.

if (builder.InvocationPointer != IntPtr.Zero)
return builder;

if (!string.IsNullOrEmpty (builder.JvmLibraryPath)) {
IntPtr errorPtr = IntPtr.Zero;
int r = NativeMethods.java_interop_jvm_load_with_error_message (builder.JvmLibraryPath, out errorPtr);
int r = NativeMethods.java_interop_jvm_load_with_error_message (builder.JvmLibraryPath!, out errorPtr);
if (r != 0) {
string error = Marshal.PtrToStringAnsi (errorPtr);
NativeMethods.java_interop_free (errorPtr);
Expand Down Expand Up @@ -166,52 +169,5 @@ 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;}
}
}
}

Loading