-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Hello-Core] Add "low level" sample. (#1047)
Rename `samples/Hello` to `samples/Hello-Java.Base`, as that sample exercises the `src/Java.Base` binding.
- Loading branch information
Showing
6 changed files
with
151 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
File renamed without changes.