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

+4
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

+7
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

+45-27
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

+13-1
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

+8
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

+4-6
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

+49-7
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

+18
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)