Skip to content

Commit 8e4c7d2

Browse files
authored
[Hello-Core] Add "low level" sample. (#1047)
Rename `samples/Hello` to `samples/Hello-Java.Base`, as that sample exercises the `src/Java.Base` binding.
1 parent e1ee4b1 commit 8e4c7d2

File tree

6 files changed

+151
-1
lines changed

6 files changed

+151
-1
lines changed

Java.Interop.sln

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "generator-Tests", "tests\ge
5959
EndProject
6060
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{D5A93398-AEB1-49F3-89DC-3904A47DB0C7}"
6161
EndProject
62-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hello", "samples\Hello\Hello.csproj", "{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}"
62+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hello-Java.Base", "samples\Hello-Java.Base\Hello-Java.Base.csproj", "{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}"
63+
EndProject
64+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hello-Core", "samples\Hello-Core\Hello-Core.csproj", "{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}"
6365
EndProject
6466
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build-Tools", "Build-Tools", "{172B608B-E6F3-41CC-9949-203A76BA247C}"
6567
EndProject
@@ -214,6 +216,10 @@ Global
214216
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Debug|Any CPU.Build.0 = Debug|Any CPU
215217
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Release|Any CPU.ActiveCfg = Release|Any CPU
216218
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9}.Release|Any CPU.Build.0 = Release|Any CPU
219+
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
220+
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}.Debug|Any CPU.Build.0 = Debug|Any CPU
221+
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}.Release|Any CPU.ActiveCfg = Release|Any CPU
222+
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461}.Release|Any CPU.Build.0 = Release|Any CPU
217223
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
218224
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
219225
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -331,6 +337,7 @@ Global
331337
{891F2E04-5614-4A26-A78F-3778025ECF43} = {271C9F30-F679-4793-942B-0D9527CB3E2F}
332338
{4EEAB1A7-99C1-4302-9C18-01A7B481409B} = {271C9F30-F679-4793-942B-0D9527CB3E2F}
333339
{F3ECB73D-9263-4E42-A5B4-3FC0D1D829F9} = {D5A93398-AEB1-49F3-89DC-3904A47DB0C7}
340+
{0E6DE9F9-35B1-4DFB-BB8B-7E4A2D362461} = {D5A93398-AEB1-49F3-89DC-3904A47DB0C7}
334341
{6410DA0F-5E14-4FC0-9AEE-F4C542C96C7A} = {172B608B-E6F3-41CC-9949-203A76BA247C}
335342
{D18FCF91-8876-48A0-A693-2DC1E7D3D80A} = {0998E45F-8BCE-4791-A944-962CD54E2D80}
336343
{D48EE8D0-0A0A-4493-AEF5-DAF5F8CF86AD} = {0998E45F-8BCE-4791-A944-962CD54E2D80}

samples/Hello-Core/Hello-Core.csproj

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(DotNetTargetFramework)</TargetFramework>
5+
<OutputType>Exe</OutputType>
6+
<RootNamespace>Hello</RootNamespace>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
<Nullable>enable</Nullable>
9+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Mono.Options" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\..\src\Java.Interop\Java.Interop.csproj" />
18+
<ProjectReference Include="..\..\src\Java.Runtime.Environment\Java.Runtime.Environment.csproj" />
19+
</ItemGroup>
20+
21+
</Project>

samples/Hello-Core/Program.cs

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using Java.Interop;
2+
3+
using Mono.Options;
4+
5+
bool showHelp = false;
6+
7+
var jreOptions = new JreRuntimeOptions {
8+
};
9+
10+
var options = new OptionSet {
11+
"Using the JVM from C#!",
12+
"",
13+
"Options:",
14+
{ "jvm=",
15+
$"{{PATH}} to JVM to use.",
16+
v => jreOptions.JvmLibraryPath = v },
17+
{ "cp=|classpath",
18+
$"Add {{JAR-OR-DIRECTORY}} to JVM classpath.",
19+
v => jreOptions.ClassPath.Add (v)},
20+
{ "J=",
21+
$"Pass the specified option to the JVM.",
22+
v => jreOptions.AddOption (v) },
23+
{ "h|help",
24+
"Show this message and exit.",
25+
v => showHelp = v != null },
26+
};
27+
options.Parse (args);
28+
29+
if (showHelp) {
30+
options.WriteOptionDescriptions (Console.Out);
31+
return;
32+
}
33+
34+
if (string.IsNullOrEmpty (jreOptions.JvmLibraryPath) || !File.Exists (jreOptions.JvmLibraryPath)) {
35+
Error ("Option -jvm=PATH is required. PATH is a full path to the JVM native library to use, e.g. `libjli.dylib`.");
36+
return;
37+
}
38+
39+
var jre = jreOptions.CreateJreVM ();
40+
41+
// We now have a JVM!
42+
// The current thread is implicitly attached to the JVM.
43+
// Access of `JniEnvironment` members on other threads will implicitly attach those threads to the JVM.
44+
45+
//
46+
// Useful background info: the JNI documentation! https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html
47+
//
48+
49+
var Object_class = JniEnvironment.Types.FindClass ("java/lang/Object");
50+
Console.WriteLine ($"Object_class={Object_class}");
51+
var Object_ctor = JniEnvironment.InstanceMethods.GetMethodID (Object_class, "<init>", "()V");
52+
var Object_val = JniEnvironment.Object.NewObject (Object_class, Object_ctor);
53+
54+
Console.WriteLine ($"Object_val={Object_val}");
55+
56+
// Invoke `Object.toString()`
57+
var Object_toString = JniEnvironment.InstanceMethods.GetMethodID (Object_class, "toString", "()Ljava/lang/String;");
58+
unsafe {
59+
var Object_desc = JniEnvironment.InstanceMethods.CallObjectMethod (Object_val, Object_toString, null);
60+
Console.WriteLine ($"Object_val.toString()={JniEnvironment.Strings.ToString (Object_desc)}");
61+
62+
// When JNI returns a `jobject` or `jclass` value, JNI returns a *JNI Object Reference*.
63+
// The `JniObjectReference` struct is used to store JNI Local, Global, and Weak Global references.
64+
//
65+
// When an object reference is no longer required, it should be explicitly deleted.
66+
67+
JniObjectReference.Dispose (ref Object_desc);
68+
}
69+
70+
JniObjectReference.Dispose (ref Object_class);
71+
JniObjectReference.Dispose (ref Object_val);
72+
73+
// There are some OO wrappers over the core `JniEnvironment` members. `JniType` is useful.
74+
var Object_type = new JniType ("java/lang/Object");
75+
var Object_ctor2 = Object_type.GetConstructor ("()V");
76+
77+
unsafe {
78+
var Object_val2 = Object_type.NewObject (Object_ctor2, null);
79+
var Object_desc = JniEnvironment.InstanceMethods.CallObjectMethod (Object_val2, Object_toString, null);
80+
Console.WriteLine ($"Object_val.toString()={JniEnvironment.Strings.ToString (Object_desc)}");
81+
}
82+
83+
void Error (string message)
84+
{
85+
var app = Path.GetFileNameWithoutExtension (Environment.GetCommandLineArgs ()[0]);
86+
Console.Error.WriteLine ($"{app}: {message}");
87+
}

samples/Hello-Core/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Hello-Core
2+
3+
Use as little of `Java.Interop.dll` as possible. No object mapping.
4+
5+
Usage:
6+
7+
```
8+
Options:
9+
--jvm=PATH PATH to JVM to use.
10+
--cp, --classpath=JAR-OR-DIRECTORY
11+
Add JAR-OR-DIRECTORY to JVM classpath.
12+
-J=VALUE Pass the specified option to the JVM.
13+
-h, --help Show this message and exit.
14+
```
15+
16+
`-J` can be used to add runtime options to the JVM instance, e.g.
17+
18+
```shell
19+
# Enable verbose JNI logging from the JVM
20+
% dotnet run -- --jvm /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/lib/jli/libjli.dylib -J-verbose:jni
21+
[Dynamic-linking native method java.lang.Object.registerNatives ... JNI]
22+
[Registering JNI native method java.lang.Object.hashCode]
23+
[Registering JNI native method java.lang.Object.wait]
24+
25+
```
26+
27+
The sample will create a `java.lang.Object` instance and invoke `Object.toString()` on it.
28+
29+
```
30+
% dotnet run -- --jvm /Library/Java/JavaVirtualMachines/microsoft-11.jdk/Contents/Home/lib/jli/libjli.dylib
31+
Object_class=0x7ff04f105b98/L
32+
Object_val=0x7ff04f105ba8/L
33+
Object_val.toString()=java.lang.Object@5cbc508c
34+
Object_val.toString()=java.lang.Object@3419866c
35+
```
File renamed without changes.

0 commit comments

Comments
 (0)