-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multithreading #19
Comments
Can you post any sample code? |
using System;
using System.IO;
using System.Collections.Generic;
using System.Reflection;
using JNet.Runtime;
using System.Threading;
namespace testJVMBridge {
public class Program {
public static JNetVirtualMachine vm = null;
public static void Main(string[] args) {
vm = JNetVirtualMachine.Initialize(new() {
JavaRuntimePath = "/Library/Java/JavaVirtualMachines/jdk-18.0.2.1.jdk/Contents/Home/",
Classpath = new List<string>() { "testfile.jar" },
});
int thread_count = 10;
for (int i = 0; i < thread_count; i++) {
Thread myThread = new Thread(Print);
myThread.Start();
}
}
static void Print() {
var rt = vm.AttachCurrentThread();
var mainClass = rt.FindClass("com/testClass");
var initMethod = rt.GetMethodID(mainClass, "<init>", "()V");
var initObj = rt.NewObject(mainClass, initMethod);
var initMainMethod = rt.GetMethodID(mainClass, "mainFunc", "()V");
rt.CallVoidMethod(initObj, initMainMethod);
vm.DetachCurrentThread();
}
}
} For example, if i specify 1 thread, it takes about ten seconds. But if i specify 10 threads, it takes more than 30 seconds. |
Managing the JNetRuntime instances by JNet.Hosting is a library that implements a host to manage the JNetRuntime instances. It is a wrapper library around the JNet.Runtime library. I recommend you to use using JNet.Hosting;
static class Program
{
static void Main(string[] args)
{
var debug = true;
JNetHost.Initialize(new() {
EnableDiagnostics = debug
});
JNetHost.Run(runtime => {
// The "runtime" parameter is a JNetRutime object, that exposes the JNI function for usage.
// See more: https://docs.oracle.com/en/java/javase/15/docs/specs/jni/functions.html
// java.lang.System class
var clz_System = runtime.FindClass("java/lang/System");
// System.out field
var f_out = runtime.GetStaticFieldID(clz_System, "out", "Ljava/io/PrintStream;");
// java.io.PrintStream class
var clz_PrintStream = runtime.FindClass("java/io/PrintStream");
// PrintStream.println method
var m_println_A = runtime.GetMethodID(clz_PrintStream, "println", "(Ljava/lang/String;)V");
// gets the System.out value
var j_out = runtime.GetStaticObjectField(clz_System, f_out);
// creates the "Hello, World!" string
var j_str = runtime.NewString("Hello, World!");
// call: System.out.println("Hello, World!")
runtime.CallVoidMethod(j_out, m_println_A, j_str);
});
JNetHost.Destroy();
}
} Calling Checkout the sample code to understand how |
And how can I run this in two threads? |
Calling |
I need to run threads as needed without deleting the Java VM, but for some reason after the thread finishes, they do not free up RAM |
I also trying your example using using JNet.Hosting;
using JNet.Runtime;
static class Program {
static void Main(string[] args) {
var debug = true;
JNetHost.Initialize(new() {
EnableDiagnostics = debug,
JavaRuntimePath = "/Library/Java/JavaVirtualMachines/jdk-18.0.2.1.jdk/Contents/Home/",
});
JNetHost.Run(runtime => {
// The "runtime" parameter is a JNetRutime object, that exposes the JNI function for usage.
// See more: https://docs.oracle.com/en/java/javase/15/docs/specs/jni/functions.html
// java.lang.System class
var clz_System = runtime.FindClass("java/lang/System");
// System.out field
var f_out = runtime.GetStaticFieldID(clz_System, "out", "Ljava/io/PrintStream;");
// java.io.PrintStream class
var clz_PrintStream = runtime.FindClass("java/io/PrintStream");
// PrintStream.println method
var m_println_A = runtime.GetMethodID(clz_PrintStream, "println", "(Ljava/lang/String;)V");
// gets the System.out value
var j_out = runtime.GetStaticObjectField(clz_System, f_out);
// creates the "Hello, World!" string
var j_str = runtime.NewString("Hello, World!");
// call: System.out.println("Hello, World!")
runtime.CallVoidMethod(j_out, m_println_A, j_str);
});
Console.ReadLine();
//JNetHost.Destroy();
}
} During execution, about 25 MB is allocated, but after the execution of the thread, during the standby mode, the memory is not released... |
I believe that this memory is the JNI libraries overhead. I simulate 100 threads and the memory comsumtion was very stable. I will investigate this when I have more time. using System;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using JNet.Hosting;
using JNet.Runtime;
static class Program
{
static void Main(string[] args)
{
PrintMemoryUsage("Program starts");
var debug = true;
PrintMemoryUsage("Before JNetHost.Initialize");
JNetHost.Initialize(new() {
EnableDiagnostics = debug
});
PrintMemoryUsage("Before JNetHost.Run");
var threads = Enumerable.Range(0, 100).Select(x => {
var thread = new Thread(() => {
JNetHost.Run(runtime => {
PrintMemoryUsage("Inside JNetHost.Run (starts)");
// The "runtime" parameter is a JNetRutime object, that exposes the JNI function for usage.
// See more: https://docs.oracle.com/en/java/javase/15/docs/specs/jni/functions.html
// java.lang.System class
var clz_System = runtime.FindClass("java/lang/System");
// System.out field
var f_out = runtime.GetStaticFieldID(clz_System, "out", "Ljava/io/PrintStream;");
// java.io.PrintStream class
var clz_PrintStream = runtime.FindClass("java/io/PrintStream");
// PrintStream.println method
var m_println_A = runtime.GetMethodID(clz_PrintStream, "println", "(Ljava/lang/String;)V");
// gets the System.out value
var j_out = runtime.GetStaticObjectField(clz_System, f_out);
// creates the "Hello, World!" string
var j_str = runtime.NewString("Hello, World!");
// call: System.out.println("Hello, World!")
runtime.CallVoidMethod(j_out, m_println_A, j_str);
runtime.ThrowExceptionOccurred();
PrintMemoryUsage("Inside JNetHost.Run (completes)");
});
});
thread.Start();
return thread;
}).ToArray();
foreach (var thread in threads) {
thread.Join();
}
PrintMemoryUsage("Before JNetHost.Destroy");
JNetHost.Destroy();
PrintMemoryUsage("Program completes");
}
static void PrintMemoryUsage(string when) {
Process currentProcess = Process.GetCurrentProcess();
long mProcess = currentProcess.WorkingSet64;
var mGc = GC.GetTotalMemory(false);
Console.WriteLine($"Memory: {when,32}: {mProcess / (1024f * 1024f),6:0.00} {mGc / (1024f * 1024f),6:0.00}");
}
} Thank you for your analisys. |
Ok, I want to use this to run a heavy function via JNI in multiple threads. One thread consumes about 200 MB, so after some time the program runs out of RAM and the kernel terminates the program. I will be very grateful when you manage to study the problem. Thanks! |
Hi, i have tried to use it in a few Threads, but it crashed. Do you have any solutions?
The text was updated successfully, but these errors were encountered: