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
9 changes: 8 additions & 1 deletion Java.Interop.sln
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "generator-Tests", "tests\ge
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{D5A93398-AEB1-49F3-89DC-3904A47DB0C7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hello", "samples\Hello\Hello.csproj", "{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hello-Java.Base", "samples\Hello-Java.Base\Hello-Java.Base.csproj", "{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hello-Core", "samples\Hello-Core\Hello-Core.csproj", "{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build-Tools", "Build-Tools", "{172B608B-E6F3-41CC-9949-203A76BA247C}"
EndProject
Expand Down Expand Up @@ -214,6 +216,10 @@ Global
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Release|Any CPU.Build.0 = Release|Any CPU
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}.Release|Any CPU.Build.0 = Release|Any CPU
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -331,6 +337,7 @@ Global
{891F2E04-5614-4A26-A78F-3778025ECF43} = {271C9F30-F679-4793-942B-0D9527CB3E2F}
{4EEAB1A7-99C1-4302-9C18-01A7B481409B} = {271C9F30-F679-4793-942B-0D9527CB3E2F}
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9} = {D5A93398-AEB1-49F3-89DC-3904A47DB0C7}
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461} = {D5A93398-AEB1-49F3-89DC-3904A47DB0C7}
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A} = {172B608B-E6F3-41CC-9949-203A76BA247C}
{D18FCF91-8876-48A0-A693-2DC1E7D3D80A} = {0998E45F-8BCE-4791-A944-962CD54E2D80}
{D48EE8D0-0A0A-4493-AEF5-DAF5F8CF86AD} = {0998E45F-8BCE-4791-A944-962CD54E2D80}
Expand Down
21 changes: 21 additions & 0 deletions samples/Hello-Core/Hello-Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DotNetTargetFramework)</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>Hello</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Mono.Options" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Java.Interop\Java.Interop.csproj" />
<ProjectReference Include="..\..\src\Java.Runtime.Environment\Java.Runtime.Environment.csproj" />
</ItemGroup>

</Project>
87 changes: 87 additions & 0 deletions samples/Hello-Core/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using Java.Interop;

using Mono.Options;

bool showHelp = false;

var jreOptions = new JreRuntimeOptions {
};

var options = new OptionSet {
"Using the JVM from C#!",
"",
"Options:",
{ "jvm=",
$"{{PATH}} to JVM to use.",
v => jreOptions.JvmLibraryPath = v },
{ "cp=|classpath",
$"Add {{JAR-OR-DIRECTORY}} to JVM classpath.",
v => jreOptions.ClassPath.Add (v)},
{ "J=",
$"Pass the specified option to the JVM.",
v => jreOptions.AddOption (v) },
{ "h|help",
"Show this message and exit.",
v => showHelp = v != null },
};
options.Parse (args);

if (showHelp) {
options.WriteOptionDescriptions (Console.Out);
return;
}

if (string.IsNullOrEmpty (jreOptions.JvmLibraryPath) || !File.Exists (jreOptions.JvmLibraryPath)) {
Error ("Option -jvm=PATH is required. PATH is a full path to the JVM native library to use, e.g. `libjli.dylib`.");
return;
}

var jre = jreOptions.CreateJreVM ();

// We now have a JVM!
// The current thread is implicitly attached to the JVM.
// Access of `JniEnvironment` members on other threads will implicitly attach those threads to the JVM.

//
// Useful background info: the JNI documentation! https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
//

var Object_class = JniEnvironment.Types.FindClass ("java/lang/Object");
Console.WriteLine ($"Object_class={Object_class}");
var Object_ctor = JniEnvironment.InstanceMethods.GetMethodID (Object_class, "<init>", "()V");
var Object_val = JniEnvironment.Object.NewObject (Object_class, Object_ctor);

Console.WriteLine ($"Object_val={Object_val}");

// Invoke `Object.toString()`
var Object_toString = JniEnvironment.InstanceMethods.GetMethodID (Object_class, "toString", "()Ljava/lang/String;");
unsafe {
var Object_desc = JniEnvironment.InstanceMethods.CallObjectMethod (Object_val, Object_toString, null);
Console.WriteLine ($"Object_val.toString()={JniEnvironment.Strings.ToString (Object_desc)}");

// When JNI returns a `jobject` or `jclass` value, JNI returns a *JNI Object Reference*.
// The `JniObjectReference` struct is used to store JNI Local, Global, and Weak Global references.
//
// When an object reference is no longer required, it should be explicitly deleted.

JniObjectReference.Dispose (ref Object_desc);
}

JniObjectReference.Dispose (ref Object_class);
JniObjectReference.Dispose (ref Object_val);

// There are some OO wrappers over the core `JniEnvironment` members. `JniType` is useful.
var Object_type = new JniType ("java/lang/Object");
var Object_ctor2 = Object_type.GetConstructor ("()V");

unsafe {
var Object_val2 = Object_type.NewObject (Object_ctor2, null);
var Object_desc = JniEnvironment.InstanceMethods.CallObjectMethod (Object_val2, Object_toString, null);
Console.WriteLine ($"Object_val.toString()={JniEnvironment.Strings.ToString (Object_desc)}");
}

void Error (string message)
{
var app = Path.GetFileNameWithoutExtension (Environment.GetCommandLineArgs ()[0]);
Console.Error.WriteLine ($"{app}: {message}");
}
35 changes: 35 additions & 0 deletions samples/Hello-Core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Hello-Core

Use as little of `Java.Interop.dll` as possible. No object mapping.

Usage:

```
Options:
--jvm=PATH PATH to JVM to use.
--cp, --classpath=JAR-OR-DIRECTORY
Add JAR-OR-DIRECTORY to JVM classpath.
-J=VALUE Pass the specified option to the JVM.
-h, --help Show this message and exit.
```

`-J` can be used to add runtime options to the JVM instance, e.g.

```shell
# Enable verbose JNI logging from the JVM
% dotnet run -- --jvm /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/lib/jli/libjli.dylib -J-verbose:jni
[Dynamic-linking native method java.lang.Object.registerNatives ... JNI]
[Registering JNI native method java.lang.Object.hashCode]
[Registering JNI native method java.lang.Object.wait]
```

The sample will create a `java.lang.Object` instance and invoke `Object.toString()` on it.

```
% dotnet run -- --jvm /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/lib/jli/libjli.dylib
Object_class=0x7ff04f105b98/L
Object_val=0x7ff04f105ba8/L
Object_val.toString()=java.lang.Object@5cbc508c
Object_val.toString()=java.lang.Object@3419866c
```
File renamed without changes.