Skip to content

Commit bc5bcf4

Browse files
authored
[Java.Base] Begin binding JDK-11 java.base module (#909)
Context: #858 What do *I* want? To be able to use our wonderful Java binding infrastructure against *Desktop Java*, not just Android. At the same time, I don't want "Android-isms" "leaking" into such a binding. *Just* Java.Interop, no xamarin-android. "Take over" the `generator --codegen-target=JavaInterop1` format so that it *isn't* useful for Xamarin.Android, and is instead usable for non-Android usage. This is a work-in-progress, and *far* from complete. For prototype purposes, this *only* binds: * `java.lang.Class` * `java.lang.Math` * `java.lang.Number` * `java.lang.Object` * `java.lang.Throwable` The `Java.Base` binding is only for .NET 6 and above. I'm not interested in .NET Standard support at this point in time. ~~ Build Changes ~~ Additionally, this `Java.Base` binding is only for the `java.base.jmod` file provided by JDK-11. `make prepare` is updated to look for a JDK-11 installation path. ~~ Test Changes ~~ Update `samples/Hello` so that it (1) works, and (2) instantiates the `Java.Lang.Object` binding: dotnet run --project samples/Hello Update `tests/generator-Tests` so that `tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/JavaInterop1` is now used *exclusively* for `generator --codegen-target=JavaInterop1` output; `generator --codegen-target=XAJavaInterop1` now has its own separate files in `tests/generator-Tests/Unit-Tests/CodeGeneratorExpectedResults/XAJavaInterop1`. (This contributes to much of the commit diff.) Update `tests/generator-Tests/SupportFiles` so that types in `Android.*` are excluded when `JAVA_INTEROP1` is `#define`d, and update the unit test infrastructure so that building for `JavaInterop1` causes `JAVA_INTEROP1` to be `#define`d. This allows many of the unit tests to ensure that *some* `JavaInterop1` constructs *compile*. However, not all unit tests compile under `JavaInterop1`. The new `BaseGeneratorTest.TryJavaInterop1` property can be set to false to prevent compiling a test suite using `JavaInterop1`. This will allow us to slowly implement `JavaInterop1` support over time. The build logs will also now emit a command-line that can be used to manually compile unit test code. See e.g. `bin/TestDebug/TestOutput-generator-Tests.txt`. ~~ API Changes ~~ Update `Java.Interop.JavaObject` so that `JavaObject.DisposeUnlessReferenced()` is now `virtual`. Override `DisposeUnlessReferenced()` from the `Java*Array` types so that if the instance was created via the new `JniEnvironment.Arrays.CreateMarshal*Array()` methods, the array instance will be disposed. This is intended for marshaling array parameters: public void WithArray(int[] array) { const string __id = "withArray.[I"; var native_array = JniEnvironment.Arrays.CreateMarshalInt32Array (array); try { JniArgumentValue* __args = stackalloc JniArgumentValue [1]; __args [0] = new JniArgumentValue (native_array); _members.StaticMethods.InvokeVoidMethod (__id, __args); } finally { if (array != null) native_array.DisposeUnlessReferenced (); } } Add `Java.Interop.JavaTypeParametersAttribute(string[] typeParameters)` from Xamarin.Android. ~~ Bindings vs. Xamarin.Android ~~ Pull in `src/Java.Base/Transforms/map.csv` [from xamarin-android][0], removing the `android*` types. Instead of `[Android.Runtime.RegisterAttribute]` on types, use `[Java.Interop.JniTypeSignatureAttribute]`. Java arrays are bound as appropriate `IList<T>`, using the `Java.Interop.Java*Array` types as an intermediary. This should help reduce marshaling logic & overhead, as if the "source" array is a `Java*Array`, it doesn't need to be "deep copied". The exception is C# `params` arrays, which continue to be bound as arrays, and are marshaled via an appropriate `Java*Array` type. `java.io.InputStream` isn't bound as `System.IO.Stream`, etc. "Java.Interop-style" constructors are used (25de1f3), e.g. // This DeclaringType (ref JniObjectReference reference, JniObjectReferenceOptions options); // Not Xamarin.Android-style DeclaringType (IntPtr handle, JniHandleOwnership transfer); "Java.Interop-style" wrapper construction is used, e.g. // This var wrapper = JniEnvironment.Runtime.ValueManager.GetValue<DeclaringType>(ref h, JniObjectReferenceOptions.CopyAndDispose); // Not this var wrapper = Java.Lang.Object.GetObject<DeclaringType>(handle); ~~ TODO: Marshal Methods ~~ Marshal methods are currently skipped. Java-to-managed invocations are not currently supported. Xamarin.Android uses Java Callable Wrappers + `Runtime.register()` to specify which methods to register, via lots of reflection, etc. Proposal: For Desktop, JCW's shouldn't need to specify all the methods to register. Instead, use the `jnimarshalmethod-gen`- originated strategy of `[JniAddNativeMethodRegistrationAttribute]` within the binding, and then have it use `MarshalMethodBuilder` to generate the marshal methods. Need to update `MarshalMethodBuilder` to look for overrides in addition to methods with `[JavaCallable]`, which in turn may require an equivalent to `[Android.Runtime.RegisterAttribute(…)]`. Perhaps `[JniMethodSignatureAttribute(string name, string sig)]`? In the meantime, `Java.Base` will skip all marshal-method logic plus runtime method generation. Leave that for later. ~~ TODO: Other Binding Changes? ~~ We should eventually "unify" `java.lang.Object` and `System.Object`. Consider `java.lang.Class`: /* partial */ class Class<T> { public boolean isInstance(java.lang.Object); public java.lang.Object[] getSigners(); } If we unify `java.lang.Object` and `System.Object`, we'd have a binding of: partial class Class { public bool IsInstance (object value); public IList<object> GetSigners(); } ~~ Open Questions ~~ What's up with `java.lang.Class.getAnnotationsByType()`? During an iteration of this PR, I got: public unsafe Java.Interop.JavaObjectArray<Java.Lang.Object>? GetAnnotationsByType (Java.Lang.Class? annotationClass) { const string __id = "getAnnotationsByType.(Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;"; From `__id` we see that the Java return type is `Annotation[]`, yet we bind it as an `Object` array? This is because of [#669][1]. That said, it's currently "differently *worse*"; I don't know why, but `__id` is now: const string __id = "getAnnotationsByType.(Ljava/lang/Class;)[Ljava/lang/Object;"; i.e. the return type is an `Object` array instead of an `Annotation` array, which is wrong, as per `javap`: % javap -s java.lang.Class … public <A extends java.lang.annotation.Annotation> A getAnnotation(java.lang.Class<A>); descriptor: (Ljava/lang/Class;)Ljava/lang/annotation/Annotation; This needs additional investigation. [0]: https://github.com/xamarin/xamarin-android/blob/99523feab02e8622a3357e9e6a025f5afc44c970/src/Mono.Android/map.csv [1]: #669
1 parent af91b9c commit bc5bcf4

File tree

462 files changed

+13758
-5050
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

462 files changed

+13758
-5050
lines changed

Directory.Build.props

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
Project="$(_OutputPath)JdkInfo.props"
3131
Condition="Exists('$(_OutputPath)JdkInfo.props')"
3232
/>
33+
<Import
34+
Project="$(_OutputPath)JdkInfo-11.props"
35+
Condition="Exists('$(_OutputPath)JdkInfo-11.props')"
36+
/>
3337
<Import
3438
Project="$(_OutputPath)MonoInfo.props"
3539
Condition="Exists('$(_OutputPath)MonoInfo.props')"

Java.Interop.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Java.Interop.Tools.JavaType
105105
EndProject
106106
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop.Tools.JavaTypeSystem-Tests", "tests\Java.Interop.Tools.JavaTypeSystem-Tests\Java.Interop.Tools.JavaTypeSystem-Tests.csproj", "{11942DE9-AEC2-4B95-87AB-CA707C37643D}"
107107
EndProject
108+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Base", "src\Java.Base\Java.Base.csproj", "{30DCECA5-16FD-4FD0-883C-E5E83B11565D}"
109+
EndProject
108110
Global
109111
GlobalSection(SharedMSBuildProjectFiles) = preSolution
110112
src\Java.Interop.NamingCustomAttributes\Java.Interop.NamingCustomAttributes.projitems*{58b564a1-570d-4da2-b02d-25bddb1a9f4f}*SharedItemsImports = 5
@@ -296,6 +298,10 @@ Global
296298
{11942DE9-AEC2-4B95-87AB-CA707C37643D}.Debug|Any CPU.Build.0 = Debug|Any CPU
297299
{11942DE9-AEC2-4B95-87AB-CA707C37643D}.Release|Any CPU.ActiveCfg = Release|Any CPU
298300
{11942DE9-AEC2-4B95-87AB-CA707C37643D}.Release|Any CPU.Build.0 = Release|Any CPU
301+
{30DCECA5-16FD-4FD0-883C-E5E83B11565D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
302+
{30DCECA5-16FD-4FD0-883C-E5E83B11565D}.Debug|Any CPU.Build.0 = Debug|Any CPU
303+
{30DCECA5-16FD-4FD0-883C-E5E83B11565D}.Release|Any CPU.ActiveCfg = Release|Any CPU
304+
{30DCECA5-16FD-4FD0-883C-E5E83B11565D}.Release|Any CPU.Build.0 = Release|Any CPU
299305
EndGlobalSection
300306
GlobalSection(SolutionProperties) = preSolution
301307
HideSolutionNode = FALSE
@@ -346,6 +352,7 @@ Global
346352
{BF5A4019-F2FF-45AC-949D-EF7E8C94196B} = {271C9F30-F679-4793-942B-0D9527CB3E2F}
347353
{B173F53B-986C-4E0D-881C-063BBB116E1D} = {0998E45F-8BCE-4791-A944-962CD54E2D80}
348354
{11942DE9-AEC2-4B95-87AB-CA707C37643D} = {271C9F30-F679-4793-942B-0D9527CB3E2F}
355+
{30DCECA5-16FD-4FD0-883C-E5E83B11565D} = {0998E45F-8BCE-4791-A944-962CD54E2D80}
349356
EndGlobalSection
350357
GlobalSection(ExtensibilityGlobals) = postSolution
351358
SolutionGuid = {29204E0C-382A-49A0-A814-AD7FBF9774A5}

build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ public class JdkInfo : Task
1919
{
2020
public string JdksRoot { get; set; }
2121

22+
public string PropertyNameModifier { get; set; } = "";
23+
public string MinimumJdkVersion { get; set; }
2224
public string MaximumJdkVersion { get; set; }
2325

2426
public string DotnetToolPath { get; set; }
@@ -28,19 +30,22 @@ public class JdkInfo : Task
2830
[Required]
2931
public ITaskItem PropertyFile { get; set; }
3032

31-
[Required]
3233
public ITaskItem MakeFragmentFile { get; set; }
3334

3435
[Output]
3536
public string JavaHomePath { get; set; }
3637

3738
public override bool Execute ()
3839
{
40+
var minVersion = GetVersion (MinimumJdkVersion);
3941
var maxVersion = GetVersion (MaximumJdkVersion);
4042

41-
XATInfo jdk = XATInfo.GetKnownSystemJdkInfos (CreateLogger ())
43+
var explicitJdks = GetJdkRoots ();
44+
var defaultJdks = XATInfo.GetKnownSystemJdkInfos (CreateLogger ())
45+
.Where (j => minVersion != null ? j.Version >= minVersion : true)
4246
.Where (j => maxVersion != null ? j.Version <= maxVersion : true)
43-
.Where (j => j.IncludePath.Any ())
47+
.Where (j => j.IncludePath.Any ());
48+
var jdk = explicitJdks.Concat (defaultJdks)
4449
.FirstOrDefault ();
4550

4651
if (jdk == null) {
@@ -56,14 +61,31 @@ public override bool Execute ()
5661
JavaHomePath = jdk.HomePath;
5762

5863
Directory.CreateDirectory (Path.GetDirectoryName (PropertyFile.ItemSpec));
59-
Directory.CreateDirectory (Path.GetDirectoryName (MakeFragmentFile.ItemSpec));
60-
6164
WritePropertyFile (jdk.JavaPath, jdk.JarPath, jdk.JavacPath, jdk.JdkJvmPath, rtJarPath, jdk.IncludePath);
62-
WriteMakeFragmentFile (jdk.JavaPath, jdk.JarPath, jdk.JavacPath, jdk.JdkJvmPath, rtJarPath, jdk.IncludePath);
65+
66+
if (MakeFragmentFile != null) {
67+
Directory.CreateDirectory (Path.GetDirectoryName (MakeFragmentFile.ItemSpec));
68+
WriteMakeFragmentFile (jdk.JavaPath, jdk.JarPath, jdk.JavacPath, jdk.JdkJvmPath, rtJarPath, jdk.IncludePath);
69+
}
6370

6471
return !Log.HasLoggedErrors;
6572
}
6673

74+
XATInfo[] GetJdkRoots ()
75+
{
76+
XATInfo jdk = null;
77+
try {
78+
if (!string.IsNullOrEmpty (JdksRoot))
79+
jdk = new XATInfo (JdksRoot);
80+
} catch (Exception e) {
81+
Log.LogWarning ($"Could not get information about JdksRoot path `{JdksRoot}`: {e.Message}");
82+
Log.LogMessage (MessageImportance.Low, e.ToString ());
83+
}
84+
return jdk == null
85+
? Array.Empty<XATInfo>()
86+
: new[] { jdk };
87+
}
88+
6789
Version GetVersion (string value)
6890
{
6991
if (string.IsNullOrEmpty (value))
@@ -97,39 +119,35 @@ Action<TraceLevel, string> CreateLogger ()
97119

98120
void WritePropertyFile (string javaPath, string jarPath, string javacPath, string jdkJvmPath, string rtJarPath, IEnumerable<string> includes)
99121
{
100-
var dotnet = string.IsNullOrEmpty (DotnetToolPath) ? "dotnet" : DotnetToolPath;
101122
var msbuild = XNamespace.Get ("http://schemas.microsoft.com/developer/msbuild/2003");
123+
var jdkJvmP = $"JdkJvm{PropertyNameModifier}Path";
102124
var project = new XElement (msbuild + "Project",
103125
new XElement (msbuild + "Choose",
104-
new XElement (msbuild + "When", new XAttribute ("Condition", " '$(JdkJvmPath)' == '' "),
126+
new XElement (msbuild + "When", new XAttribute ("Condition", $" '$({jdkJvmP})' == '' "),
105127
new XElement (msbuild + "PropertyGroup",
106-
new XElement (msbuild + "JdkJvmPath", jdkJvmPath)),
128+
new XElement (msbuild + jdkJvmP, jdkJvmPath)),
107129
new XElement (msbuild + "ItemGroup",
108-
includes.Select (i => new XElement (msbuild + "JdkIncludePath", new XAttribute ("Include", i)))))),
130+
includes.Select (i => new XElement (msbuild + $"Jdk{PropertyNameModifier}IncludePath", new XAttribute ("Include", i)))))),
109131
new XElement (msbuild + "PropertyGroup",
110-
new XElement (msbuild + "JavaSdkDirectory", new XAttribute ("Condition", " '$(JavaSdkDirectory)' == '' "),
111-
JavaHomePath),
112-
new XElement (msbuild + "JavaPath", new XAttribute ("Condition", " '$(JavaPath)' == '' "),
113-
javaPath),
114-
new XElement (msbuild + "JavaCPath", new XAttribute ("Condition", " '$(JavaCPath)' == '' "),
115-
javacPath),
116-
new XElement (msbuild + "JarPath", new XAttribute ("Condition", " '$(JarPath)' == '' "),
117-
jarPath),
118-
new XElement (msbuild + "DotnetToolPath", new XAttribute ("Condition", " '$(DotnetToolPath)' == '' "),
119-
dotnet),
120-
CreateJreRtJarPath (msbuild, rtJarPath)));
132+
CreateProperty (msbuild, $"Java{PropertyNameModifier}SdkDirectory", JavaHomePath),
133+
CreateProperty (msbuild, $"Java{PropertyNameModifier}Path", javaPath),
134+
CreateProperty (msbuild, $"JavaC{PropertyNameModifier}Path", javacPath),
135+
CreateProperty (msbuild, $"Jar{PropertyNameModifier}Path", jarPath),
136+
CreateProperty (msbuild, $"Dotnet{PropertyNameModifier}ToolPath", DotnetToolPath),
137+
CreateProperty (msbuild, $"Jre{PropertyNameModifier}RtJarPath", rtJarPath)));
121138
project.Save (PropertyFile.ItemSpec);
122139
}
123140

124-
static XElement CreateJreRtJarPath (XNamespace msbuild, string rtJarPath)
141+
XElement CreateProperty (XNamespace msbuild, string propertyName, string propertyValue)
125142
{
126-
if (rtJarPath == null)
143+
if (string.IsNullOrEmpty (propertyValue)) {
127144
return null;
128-
return new XElement (msbuild + "JreRtJarPath",
129-
new XAttribute ("Condition", " '$(JreRtJarPath)' == '' "),
130-
rtJarPath);
131-
}
145+
}
132146

147+
return new XElement (msbuild + propertyName,
148+
new XAttribute ("Condition", $" '$({propertyName})' == '' "),
149+
propertyValue);
150+
}
133151
void WriteMakeFragmentFile (string javaPath, string jarPath, string javacPath, string jdkJvmPath, string rtJarPath, IEnumerable<string> includes)
134152
{
135153
using (var o = new StreamWriter (MakeFragmentFile.ItemSpec)) {

build-tools/scripts/Prepare.targets

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,26 @@
1313
<PropertyGroup>
1414
<_MaxJdk>$(MaxJdkVersion)</_MaxJdk>
1515
<_MaxJdk Condition=" '$(_MaxJdk)' == '' ">$(JI_MAX_JDK)</_MaxJdk>
16+
<Jdks8Root Condition=" '$(Jdks8Root)' == '' And '$(JAVA_HOME_8_X64)' != '' And Exists($(JAVA_HOME_8_X64)) ">$(JAVA_HOME_8_X64)</Jdks8Root>
1617
</PropertyGroup>
1718
<JdkInfo
18-
JdksRoot="$(ProgramFiles)\Java"
19+
JdksRoot="$(Jdks8Root)"
1920
MakeFragmentFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\JdkInfo.mk"
2021
MaximumJdkVersion="$(_MaxJdk)"
2122
DotnetToolPath="$(DotnetToolPath)"
2223
PropertyFile="$(_TopDir)\bin\Build$(Configuration)\JdkInfo.props">
2324
<Output TaskParameter="JavaHomePath" PropertyName="_JavaSdkDirectory" />
2425
</JdkInfo>
26+
<PropertyGroup>
27+
<Jdks11Root Condition=" '$(Jdks11Root)' == '' And '$(JAVA_HOME_11_X64)' != '' And Exists($(JAVA_HOME_11_X64)) ">$(JAVA_HOME_11_X64)</Jdks11Root>
28+
</PropertyGroup>
29+
<JdkInfo
30+
JdksRoot="$(Jdks11Root)"
31+
PropertyNameModifier="11"
32+
MinimumJdkVersion="11.0"
33+
MaximumJdkVersion="11.99.0"
34+
PropertyFile="$(_TopDir)\bin\Build$(Configuration)\JdkInfo-11.props">
35+
<Output TaskParameter="JavaHomePath" PropertyName="Java11SdkDirectory"/>
36+
</JdkInfo>
2537
</Target>
2638
</Project>

build-tools/scripts/jdk.targets

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,13 @@
1010
PropertyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\JdkInfo.props">
1111
<Output TaskParameter="JavaHomePath" PropertyName="_JavaHome"/>
1212
</JdkInfo>
13+
<JdkInfo
14+
JdksRoot="$(JdksRoot)"
15+
PropertyNameModifier="11"
16+
MinimumJdkVersion="11.0"
17+
MaximumJdkVersion="11.99.0"
18+
PropertyFile="$(MSBuildThisFileDirectory)..\..\bin\Build$(Configuration)\JdkInfo-11.props">
19+
<Output TaskParameter="JavaHomePath" PropertyName="Java11SdkDirectory"/>
20+
</JdkInfo>
1321
</Target>
1422
</Project>

samples/Hello/Hello.csproj

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net472</TargetFramework>
4+
<TargetFramework>net6.0</TargetFramework>
55
<OutputType>Exe</OutputType>
6-
<OutputPath>..\..\bin\Test$(Configuration)</OutputPath>
76
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
8-
</PropertyGroup>
9-
10-
<PropertyGroup>
11-
<OutputPath>$(TestOutputFullPath)</OutputPath>
7+
<Nullable>enable</Nullable>
128
</PropertyGroup>
139

1410
<ItemGroup>
@@ -18,6 +14,8 @@
1814
<ItemGroup>
1915
<ProjectReference Include="..\..\src\Java.Interop\Java.Interop.csproj" />
2016
<ProjectReference Include="..\..\src\Java.Runtime.Environment\Java.Runtime.Environment.csproj" />
17+
<ProjectReference Include="..\..\src\Java.Base\Java.Base.csproj" />
18+
<ProjectReference Include="..\..\tests\TestJVM\TestJVM.csproj" />
2119
</ItemGroup>
2220

2321
</Project>

samples/Hello/Program.cs

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,65 @@
11
using System;
22
using System.Threading;
33

4+
using Mono.Options;
5+
46
using Java.Interop;
57

68
namespace Hello
79
{
8-
class MainClass
10+
class App
911
{
10-
public static unsafe void Main (string[] args)
12+
public static void Main (string[] args)
1113
{
12-
Console.WriteLine ("Hello World!");
13-
try {
14-
var ignore = JniRuntime.CurrentRuntime;
15-
} catch (InvalidOperationException e) {
16-
Console.WriteLine (e);
14+
string? jvmPath = global::Java.InteropTests.TestJVM.GetJvmLibraryPath ();
15+
bool createMultipleVMs = false;
16+
bool showHelp = false;
17+
var options = new OptionSet () {
18+
"Using the JVM from C#!",
19+
"",
20+
"Options:",
21+
{ "jvm=",
22+
$"{{PATH}} to JVM to use. Default is:\n {jvmPath}",
23+
v => jvmPath = v },
24+
{ "m",
25+
"Create multiple Java VMs. This will likely creash.",
26+
v => createMultipleVMs = v != null },
27+
{ "h|help",
28+
"Show this message and exit.",
29+
v => showHelp = v != null },
30+
};
31+
options.Parse (args);
32+
if (showHelp) {
33+
options.WriteOptionDescriptions (Console.Out);
34+
return;
1735
}
36+
Console.WriteLine ("Hello World!");
37+
var builder = new JreRuntimeOptions () {
38+
JniAddNativeMethodRegistrationAttributePresent = true,
39+
JvmLibraryPath = jvmPath,
40+
};
41+
builder.AddOption ("-Xcheck:jni");
42+
var jvm = builder.CreateJreVM ();
43+
Console.WriteLine ($"JniRuntime.CurrentRuntime == jvm? {ReferenceEquals (JniRuntime.CurrentRuntime, jvm)}");
1844
foreach (var h in JniRuntime.GetAvailableInvocationPointers ()) {
1945
Console.WriteLine ("PRE: GetCreatedJavaVMHandles: {0}", h);
2046
}
47+
48+
CreateJLO ();
49+
50+
if (createMultipleVMs) {
51+
CreateAnotherJVM ();
52+
}
53+
}
54+
55+
static void CreateJLO ()
56+
{
57+
var jlo = new Java.Lang.Object ();
58+
Console.WriteLine ($"binding? {jlo.ToString ()}");
59+
}
60+
61+
static unsafe void CreateAnotherJVM ()
62+
{
2163
Console.WriteLine ("Part 2!");
2264
using (var vm = new JreRuntimeOptions ().CreateJreVM ()) {
2365
Console.WriteLine ("# JniEnvironment.EnvironmentPointer={0}", JniEnvironment.EnvironmentPointer);

src/Java.Base/Java.Base.csproj

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFrameworks>net6.0</TargetFrameworks>
5+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
6+
<Nullable>enable</Nullable>
7+
<NoWarn>8764</NoWarn>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\Java.Interop\Java.Interop.csproj" />
12+
<ProjectReference Include="..\..\tools\class-parse\class-parse.csproj" ReferenceOutputAssembly="False" />
13+
<ProjectReference Include="..\..\tools\generator\generator.csproj" ReferenceOutputAssembly="False" />
14+
</ItemGroup>
15+
16+
<Import Project="Java.Base.targets" />
17+
18+
</Project>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy