Skip to content

Commit

Permalink
Update documentation after commit 284b237
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Oct 10, 2023
1 parent 284b237 commit c72cc25
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 32 deletions.
194 changes: 163 additions & 31 deletions docs/articles/usage.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,45 @@ <h1 id="jnet-usage">JNet usage</h1>

<p>To use JNet classes the developer can write code in .NET using the same classes available in the official Java packages.
If classes or methods are not available yet it is possible to use the approach synthetized in <a href="API_extensibility.html">What to do if an API was not yet implemented</a></p>
<h2 id="environment-setup">Environment setup</h2>
<p>JNet accepts many command-line switches to customize its behavior. The full list is available at <a href="commandlineswitch.html">Command line switch</a> page.</p>
<h3 id="jvm-identification">JVM identification</h3>
<p>One of the most important command-line switch is <strong>JVMPath</strong> and it is available in <a href="https://www.jcobridge.com/net-examples/command-line-options/">JCOBridge switches</a>: it can be used to set-up the location of the JVM library (jvm.dll/libjvm.so) if JCOBridge is not able to identify a suitable JRE installation.
If a developer is using JNet within its own product it is possible to override the <strong>JVMPath</strong> property with a snippet like the following one:</p>
<pre><code class="lang-c#"> class MyJNetCore : JNetCore
{
public override string JVMPath
{
get
{
string pathToJVM = &quot;Set here the path to JVM library or use your own search method&quot;;
return pathToJVM;
}
}
}
</code></pre>
<p><strong>IMPORTANT NOTE</strong>: <code>pathToJVM</code> shall be escaped</p>
<ol>
<li><code>string pathToJVM = &quot;C:\\Program Files\\Eclipse Adoptium\\jdk-11.0.18.10-hotspot\\bin\\server\\jvm.dll&quot;;</code></li>
<li><code>string pathToJVM = @&quot;C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\bin\server\jvm.dll&quot;;</code></li>
</ol>
<h3 id="special-initialization-conditions">Special initialization conditions</h3>
<p><a href="https://www.jcobridge.com/">JCOBridge</a> try to identify a suitable JRE/JDK installation within the system using some standard mechanism of JRE/JDK: <code>JAVA_HOME</code> environment variable or Windows registry if available.
However it is possible, on Windows operating systems, that the library raises an <strong>InvalidOperationException: Missing Java Key in registry: Couldn't find Java installed on the machine</strong>.
This means that neither <code>JAVA_HOME</code> nor Windows registry contains information about a default installed JRE/JDK: some vendors may not setup them.
If the developer/user encounter this condition can do the following steps:</p>
<ol>
<li>On a command prompt execute <code>set | findstr JAVA_HOME</code> and verify the result;</li>
<li>If something was reported maybe the <code>JAVA_HOME</code> environment variable is not set at system level, but at a different level like user level which is not visible from the JNet process that raised the exception;</li>
<li>Try to set <code>JAVA_HOME</code> at system level e.g. <code>JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\</code>;</li>
<li>Try to set <code>JCOBRIDGE_JVMPath</code> at system level e.g. <code>JCOBRIDGE_JVMPath=C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\</code>.</li>
</ol>
<p><strong>IMPORTANT NOTES</strong>:</p>
<ul>
<li>One of <code>JCOBRIDGE_JVMPath</code> or <code>JAVA_HOME</code> environment variables or Windows registry (on Windows OSes) shall be available</li>
<li><code>JCOBRIDGE_JVMPath</code> environment variable takes precedence over <code>JAVA_HOME</code> and Windows registry: you can set <code>JCOBRIDGE_JVMPath</code> to <code>C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\bin\server\jvm.dll</code> and avoid to override <code>JVMPath</code> in your code</li>
<li>After first initialization steps, <code>JVMPath</code> takes precedence over <code>JCOBRIDGE_JVMPath</code>/<code>JAVA_HOME</code> environment variables or Windows registry</li>
</ul>
<h2 id="basic-example">Basic example</h2>
<p>Below a basic example which demonstrates how to create a program based on JNet and some other features available like generics and exception handling.
Within the program the comments try to explain how the code works.</p>
Expand Down Expand Up @@ -102,7 +141,8 @@ <h2 id="basic-example">Basic example</h2>
{
// in the first step the code allocates a java.util.Set&lt;String&gt; within the JVM using the java.util.Collections class
// and returns a Java.Util.Set&lt;string&gt; in .NET
var set = Collections.Singleton(&quot;test&quot;);
Java.Util.Set&lt;string&gt; set = Collections.Singleton(&quot;test&quot;);

// then the code tries to Add a new value if it is available in command-line,
// but we expect the JVM raises an exception
if (appArgs.Length != 0) set.Add(appArgs[0]);
Expand All @@ -121,45 +161,137 @@ <h2 id="basic-example">Basic example</h2>
}
}
</code></pre>
<h2 id="environment-setup">Environment setup</h2>
<p>JNet accepts many command-line switches to customize its behavior. The full list is available at <a href="commandlineswitch.html">Command line switch</a> page.</p>
<h3 id="jvm-identification">JVM identification</h3>
<p>One of the most important command-line switch is <strong>JVMPath</strong> and it is available in <a href="https://www.jcobridge.com/net-examples/command-line-options/">JCOBridge switches</a>: it can be used to set-up the location of the JVM library (jvm.dll/libjvm.so) if JCOBridge is not able to identify a suitable JRE installation.
If a developer is using JNet within its own product it is possible to override the <strong>JVMPath</strong> property with a snippet like the following one:</p>
<pre><code class="lang-c#"> class MyJNetCore : JNetCore
<h2 id="avoid-javalangnullpointerexception-writing-a-good-code">Avoid <code>Java.Lang.NullPointerException</code> writing a good code</h2>
<p>Sometime during execution a <code>Java.Lang.NullPointerException</code> can be raised and seems there isn't neither a real problem in the .NET code you wrote nor a specific pattern or time when it is raised.
The problem is behind the scene and it is correlated on how Garbage Collector and code optimizer works.
In the code of the previous chapter the <code>Collections.Singleton(&quot;test&quot;)</code> creates an object which is used from <code>set.Add(appArgs[0])</code> and in this case the Garbage Collector does not retires the object.
Considering the following code snippet:</p>
<pre><code class="lang-c#">using Java.Util;
using MASES.JNet.Extensions;
using System.Diagnostics;
using Java.Lang;

namespace MASES.JNetExample
{
class MyJNetCore : JNetCore&lt;MyJNetCore&gt; { }

class Program
{
public override string JVMPath
static void Main(string[] args)
{
get
MyJNetCore.CreateGlobalInstance();
try
{
string pathToJVM = &quot;Set here the path to JVM library or use your own search method&quot;;
return pathToJVM;
Java.Util.Set&lt;string&gt; set = Collections.Singleton(&quot;test&quot;);
ArrayList&lt;string&gt; arrayList = new();
arrayList.AddAll(0, set); // this point can raise Java.Lang.NullPointerException
}
catch (System.Exception ex) { System.Console.WriteLine(ex.Message); }
}
}
}
</code></pre>
<p><strong>IMPORTANT NOTE</strong>: <code>pathToJVM</code> shall be escaped</p>
<ol>
<li><code>string pathToJVM = &quot;C:\\Program Files\\Eclipse Adoptium\\jdk-11.0.18.10-hotspot\\bin\\server\\jvm.dll&quot;;</code></li>
<li><code>string pathToJVM = @&quot;C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\bin\server\jvm.dll&quot;;</code></li>
</ol>
<h3 id="special-initialization-conditions">Special initialization conditions</h3>
<p><a href="https://www.jcobridge.com/">JCOBridge</a> try to identify a suitable JRE/JDK installation within the system using some standard mechanism of JRE/JDK: <code>JAVA_HOME</code> environment variable or Windows registry if available.
However it is possible, on Windows operating systems, that the library raises an <strong>InvalidOperationException: Missing Java Key in registry: Couldn't find Java installed on the machine</strong>.
This means that neither <code>JAVA_HOME</code> nor Windows registry contains information about a default installed JRE/JDK: some vendors may not setup them.
If the developer/user encounter this condition can do the following steps:</p>
<ol>
<li>On a command prompt execute <code>set | findstr JAVA_HOME</code> and verify the result;</li>
<li>If something was reported maybe the <code>JAVA_HOME</code> environment variable is not set at system level, but at a different level like user level which is not visible from the JNet process that raised the exception;</li>
<li>Try to set <code>JAVA_HOME</code> at system level e.g. <code>JAVA_HOME=C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\</code>;</li>
<li>Try to set <code>JCOBRIDGE_JVMPath</code> at system level e.g. <code>JCOBRIDGE_JVMPath=C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\</code>.</li>
</ol>
<p><strong>IMPORTANT NOTES</strong>:</p>
<p>the <code>Collections.Singleton(&quot;test&quot;)</code> ends its life, from .NET point of view, when <code>arrayList.AddAll(0, set)</code> is invoked:</p>
<ul>
<li>One of <code>JCOBRIDGE_JVMPath</code> or <code>JAVA_HOME</code> environment variables or Windows registry (on Windows OSes) shall be available</li>
<li><code>JCOBRIDGE_JVMPath</code> environment variable takes precedence over <code>JAVA_HOME</code> and Windows registry: you can set <code>JCOBRIDGE_JVMPath</code> to <code>C:\Program Files\Eclipse Adoptium\jdk-11.0.18.10-hotspot\bin\server\jvm.dll</code> and avoid to override <code>JVMPath</code> in your code</li>
<li>After first initialization steps, <code>JVMPath</code> takes precedence over <code>JCOBRIDGE_JVMPath</code>/<code>JAVA_HOME</code> environment variables or Windows registry</li>
<li><code>Java.Util.Set&lt;string&gt;</code> is a .NET container for JVM <code>java.util.Set&lt;String&gt;</code></li>
<li><code>arrayList.AddAll(0, set)</code> receives the <code>Java.Util.Set&lt;string&gt;</code> instance and sends to JVM the reference to <code>java.util.Set&lt;String&gt;</code> of JVM</li>
<li>from .NET point of view <code>Java.Util.Set&lt;string&gt;</code> has ended its life and can be retired because does not have any other root referencing it</li>
<li>.NET Garbage Collector activates arbitrarily when some conditions meet: <a href="https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/">https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/</a></li>
</ul>
<p>Most of the time the code above works without problem, but sometimes the JVM can raise a <code>Java.Lang.NullPointerException</code> because <code>Java.Util.Set&lt;string&gt;</code> was retired from .NET GC.</p>
<p>To solve the issue, and force the GC to not retire the instance, there are some possible code snippet a developer can follows:</p>
<h3 id="using-or-try-finally-with-dispose-patterns"><code>using</code> or <code>try-finally</code> with <code>Dispose</code> patterns</h3>
<p>All classes implements <code>IDisposable</code> interface, the code snippet becomes:</p>
<pre><code class="lang-c#">using Java.Util;
using MASES.JNet.Extensions;
using System.Diagnostics;
using Java.Lang;

namespace MASES.JNetExample
{
class MyJNetCore : JNetCore&lt;MyJNetCore&gt; { }

class Program
{
static void Main(string[] args)
{
MyJNetCore.CreateGlobalInstance();
try
{
using (Java.Util.Set&lt;string&gt; set = Collections.Singleton(&quot;test&quot;))
{
ArrayList&lt;string&gt; arrayList = new();
arrayList.AddAll(0, set);
}
}
catch (System.Exception ex) { System.Console.WriteLine(ex.Message); }
}
}
}
</code></pre>
<p>or</p>
<pre><code class="lang-c#">using Java.Util;
using MASES.JNet.Extensions;
using System.Diagnostics;
using Java.Lang;

namespace MASES.JNetExample
{
class MyJNetCore : JNetCore&lt;MyJNetCore&gt; { }

class Program
{
static void Main(string[] args)
{
MyJNetCore.CreateGlobalInstance();
try
{
Java.Util.Set&lt;string&gt; set = null;
try
{
set = Collections.Singleton(&quot;test&quot;);
ArrayList&lt;string&gt; arrayList = new();
arrayList.AddAll(0, set);
}
finally { set?.Dispose(); }
}
catch (System.Exception ex) { System.Console.WriteLine(ex.Message); }
}
}
}
</code></pre>
<h3 id="suppressfinalizereregisterforfinalize-pattern"><code>SuppressFinalize</code>/<code>ReRegisterForFinalize</code> pattern</h3>
<p>Over every .NET object can be invoke the <code>SuppressFinalize</code>, the code snippet becomes:</p>
<pre><code class="lang-c#">using Java.Util;
using MASES.JNet.Extensions;
using System.Diagnostics;
using Java.Lang;

namespace MASES.JNetExample
{
class MyJNetCore : JNetCore&lt;MyJNetCore&gt; { }

class Program
{
static void Main(string[] args)
{
MyJNetCore.CreateGlobalInstance();
try
{
Java.Util.Set&lt;string&gt; set = Collections.Singleton(&quot;test&quot;);
try
{
System.GC.SuppressFinalize(set);
ArrayList&lt;string&gt; arrayList = new();
arrayList.AddAll(0, set);
}
finally { System.GC.ReRegisterForFinalize(set); }
}
catch (System.Exception ex) { System.Console.WriteLine(ex.Message); }
}
}
}
</code></pre>
</article>
</div>

Expand Down
2 changes: 1 addition & 1 deletion docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -63396,7 +63396,7 @@
"output": {
".html": {
"relative_path": "articles/usage.html",
"hash": "dyMnYAytqlHpKY28VBfBluH0Ma1alHb1ZXtirNzZAns="
"hash": "cTawMw2ZiTo/593NjfMpbvpf4CJrtXzzlESakvOl7Bo="
}
},
"is_incremental": false,
Expand Down

0 comments on commit c72cc25

Please sign in to comment.