diff --git a/launcher/backend/include_public/DhfsInstance.hpp b/launcher/backend/include_public/DhfsInstance.hpp index 6001df50..8f854685 100644 --- a/launcher/backend/include_public/DhfsInstance.hpp +++ b/launcher/backend/include_public/DhfsInstance.hpp @@ -6,6 +6,8 @@ #define DHFSINSTANCE_HPP #include +#include +#include enum class DhfsInstanceState { RUNNING, @@ -20,7 +22,7 @@ public: DhfsInstanceState state(); - void start(); + void start(const std::string& mount_path, const std::vector& extra_options); void stop(); @@ -28,7 +30,7 @@ private: DhfsInstanceState _state = DhfsInstanceState::STOPPED; JavaVM* _jvm = nullptr; - JNIEnv *_env = nullptr; + JNIEnv* _env = nullptr; }; diff --git a/launcher/backend/src/DhfsInstance.cpp b/launcher/backend/src/DhfsInstance.cpp index 25be22da..7409aa35 100644 --- a/launcher/backend/src/DhfsInstance.cpp +++ b/launcher/backend/src/DhfsInstance.cpp @@ -7,6 +7,7 @@ #include #include +#include "Exception.h" #include "LibjvmWrapper.hpp" DhfsInstance::DhfsInstance() { @@ -16,9 +17,10 @@ DhfsInstance::~DhfsInstance() { } DhfsInstanceState DhfsInstance::state() { + return _state; } -void DhfsInstance::start() { +void DhfsInstance::start(const std::string& mount_path, const std::vector& extra_options) { switch (_state) { case DhfsInstanceState::RUNNING: return; @@ -27,15 +29,22 @@ void DhfsInstance::start() { default: throw std::runtime_error("Unknown DhfsInstanceState"); } + _state = DhfsInstanceState::RUNNING; JavaVMInitArgs args; std::vector options; + for (const auto& option: extra_options) { + options.emplace_back((char*) option.c_str(), nullptr); + } + std::string mount_option = "-Ddhfs.fuse.root="; + mount_option += mount_path; + options.emplace_back((char*) mount_option.c_str(), nullptr); args.version = JNI_VERSION_21; - args.nOptions = 0; + args.nOptions = options.size(); args.options = options.data(); args.ignoreUnrecognized = false; - LibjvmWrapper::instance().WJNI_CreateJavaVM(&_jvm, (void**) &_env, &args); + LibjvmWrapper::instance().get_JNI_CreateJavaVM()(&_jvm, (void**) &_env, &args); } void DhfsInstance::stop() { @@ -47,4 +56,13 @@ void DhfsInstance::stop() { default: throw std::runtime_error("Unknown DhfsInstanceState"); } + + if (_jvm == nullptr) + throw Exception("JVM not running"); + + JNIEnv* env; + _jvm->AttachCurrentThread((void**) &env, nullptr); + _jvm->DestroyJavaVM(); + _jvm = nullptr; + _state = DhfsInstanceState::STOPPED; } diff --git a/launcher/gui/src/GLauncherApp.cpp b/launcher/gui/src/GLauncherApp.cpp index 1b35bcb0..6e1627e9 100644 --- a/launcher/gui/src/GLauncherApp.cpp +++ b/launcher/gui/src/GLauncherApp.cpp @@ -30,9 +30,9 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co gbSizer1->SetFlexibleDirection( wxBOTH ); gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); - m_staticText1 = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, _("Running"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1->Wrap( -1 ); - gbSizer1->Add( m_staticText1, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 ); + m_statusText = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, _("Running"), wxDefaultPosition, wxDefaultSize, 0 ); + m_statusText->Wrap( -1 ); + gbSizer1->Add( m_statusText, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 ); m_startStopButton = new wxButton( sbSizer4->GetStaticBox(), wxID_ANY, _("Start"), wxDefaultPosition, wxDefaultSize, 0 ); gbSizer1->Add( m_startStopButton, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALL, 5 ); @@ -41,23 +41,84 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co sbSizer4->Add( gbSizer1, 1, wxEXPAND, 5 ); - bSizer2->Add( sbSizer4, 1, wxEXPAND, 5 ); + bSizer2->Add( sbSizer4, 1, wxALL|wxEXPAND, 5 ); wxStaticBoxSizer* sbSizer6; sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( m_panel1, wxID_ANY, _("Statistics") ), wxVERTICAL ); - bSizer2->Add( sbSizer6, 1, wxEXPAND, 5 ); + bSizer2->Add( sbSizer6, 1, wxALL|wxEXPAND, 5 ); m_panel1->SetSizer( bSizer2 ); m_panel1->Layout(); bSizer2->Fit( m_panel1 ); - m_notebook1->AddPage( m_panel1, _("Info"), true ); + m_notebook1->AddPage( m_panel1, _("Info"), false ); m_panel3 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); m_notebook1->AddPage( m_panel3, _("Logs"), false ); m_panel2 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); - m_notebook1->AddPage( m_panel2, _("Settings"), false ); + wxBoxSizer* bSizer5; + bSizer5 = new wxBoxSizer( wxVERTICAL ); + + wxStaticBoxSizer* sbSizer3; + sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panel2, wxID_ANY, _("JVM") ), wxVERTICAL ); + + wxGridBagSizer* gbSizer2; + gbSizer2 = new wxGridBagSizer( 0, 0 ); + gbSizer2->SetFlexibleDirection( wxBOTH ); + gbSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_button2 = new wxButton( sbSizer3->GetStaticBox(), wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, 0 ); + gbSizer2->Add( m_button2, wxGBPosition( 0, 3 ), wxGBSpan( 1, 1 ), wxALL, 5 ); + + + gbSizer2->Add( 50, 0, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 ); + + m_javaHomeDirPicker = new wxDirPickerCtrl( sbSizer3->GetStaticBox(), wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, wxDIRP_DEFAULT_STYLE|wxDIRP_USE_TEXTCTRL ); + gbSizer2->Add( m_javaHomeDirPicker, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 ); + + m_staticText2 = new wxStaticText( sbSizer3->GetStaticBox(), wxID_ANY, _("Java Home"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText2->Wrap( -1 ); + gbSizer2->Add( m_staticText2, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + gbSizer2->AddGrowableCol( 1 ); + + sbSizer3->Add( gbSizer2, 1, wxEXPAND, 5 ); + + + bSizer5->Add( sbSizer3, 1, wxALL|wxEXPAND|wxFIXED_MINSIZE, 5 ); + + wxStaticBoxSizer* sbSizer41; + sbSizer41 = new wxStaticBoxSizer( new wxStaticBox( m_panel2, wxID_ANY, _("Paths") ), wxVERTICAL ); + + wxGridBagSizer* gbSizer3; + gbSizer3 = new wxGridBagSizer( 0, 0 ); + gbSizer3->SetFlexibleDirection( wxBOTH ); + gbSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticText6 = new wxStaticText( sbSizer41->GetStaticBox(), wxID_ANY, _("Mount path"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText6->Wrap( -1 ); + gbSizer3->Add( m_staticText6, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_mountPathDirPicker = new wxDirPickerCtrl( sbSizer41->GetStaticBox(), wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, wxDIRP_DEFAULT_STYLE|wxDIRP_USE_TEXTCTRL ); + gbSizer3->Add( m_mountPathDirPicker, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 ); + + + gbSizer3->AddGrowableCol( 1 ); + + sbSizer41->Add( gbSizer3, 1, wxEXPAND, 5 ); + + + bSizer5->Add( sbSizer41, 1, wxALL|wxEXPAND, 5 ); + + + m_panel2->SetSizer( bSizer5 ); + m_panel2->Layout(); + bSizer5->Fit( m_panel2 ); + m_notebook1->AddPage( m_panel2, _("Settings"), true ); + m_panel4 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); + m_notebook1->AddPage( m_panel4, _("Advanced Settings"), false ); bSizer3->Add( m_notebook1, 1, wxALL|wxEXPAND, 5 ); @@ -69,6 +130,8 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co // Connect Events m_startStopButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::OnStartStopButtonClick ), NULL, this ); + m_javaHomeDirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainFrame::OnJavaHomeChanged ), NULL, this ); + m_mountPathDirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainFrame::OnMountPathChanged ), NULL, this ); } MainFrame::~MainFrame() diff --git a/launcher/gui/src/GLauncherApp.h b/launcher/gui/src/GLauncherApp.h index 53a50238..24c617c3 100644 --- a/launcher/gui/src/GLauncherApp.h +++ b/launcher/gui/src/GLauncherApp.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -41,18 +42,26 @@ class MainFrame : public wxFrame wxStatusBar* m_statusBar1; wxNotebook* m_notebook1; wxPanel* m_panel1; - wxStaticText* m_staticText1; + wxStaticText* m_statusText; wxButton* m_startStopButton; wxPanel* m_panel3; wxPanel* m_panel2; + wxButton* m_button2; + wxDirPickerCtrl* m_javaHomeDirPicker; + wxStaticText* m_staticText2; + wxStaticText* m_staticText6; + wxDirPickerCtrl* m_mountPathDirPicker; + wxPanel* m_panel4; // Virtual event handlers, override them in your derived class virtual void OnStartStopButtonClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnJavaHomeChanged( wxFileDirPickerEvent& event ) { event.Skip(); } + virtual void OnMountPathChanged( wxFileDirPickerEvent& event ) { event.Skip(); } public: - MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("DHFS"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL, const wxString& name = wxT("DHFS") ); + MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("DHFS"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 499,341 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL, const wxString& name = wxT("DHFS") ); ~MainFrame(); diff --git a/launcher/gui/src/LauncherApp.cpp b/launcher/gui/src/LauncherApp.cpp index 636e3a04..c46e9ebe 100644 --- a/launcher/gui/src/LauncherApp.cpp +++ b/launcher/gui/src/LauncherApp.cpp @@ -15,11 +15,13 @@ #include "LauncherAppMainFrame.h" #include "wx/taskbar.h" - +#include IMPLEMENT_APP(LauncherApp) // This is executed upon startup, like 'main()' in non-wxWidgets programs. bool LauncherApp::OnInit() { + wxFileConfig::Get()->SetAppName("DHFS"); + wxFrame* frame = new LauncherAppMainFrame(NULL); frame->Show(true); SetTopWindow(frame); diff --git a/launcher/gui/src/LauncherAppMainFrame.cpp b/launcher/gui/src/LauncherAppMainFrame.cpp index f4eea2f7..547edbe8 100644 --- a/launcher/gui/src/LauncherAppMainFrame.cpp +++ b/launcher/gui/src/LauncherAppMainFrame.cpp @@ -1,13 +1,43 @@ #include "LauncherAppMainFrame.h" #include +#include + +#include "Exception.h" +#include "LibjvmWrapper.hpp" LauncherAppMainFrame::LauncherAppMainFrame(wxWindow* parent) : MainFrame(parent) { + m_javaHomeDirPicker->SetPath(wxFileConfig::Get()->Read(kJavaHomeSettingsKey)); + m_mountPathDirPicker->SetPath(wxFileConfig::Get()->Read(kMountPointSettingsKey)); } void LauncherAppMainFrame::OnStartStopButtonClick(wxCommandEvent& event) { - std::cout << "Hi!" << std::endl; - _dhfsInstance.start(); - // TODO: Implement OnStartStopButtonClick + switch (_dhfsInstance.state()) { + case DhfsInstanceState::RUNNING: + m_statusText->SetLabel("Stopped"); + m_startStopButton->SetLabel("Start"); + m_statusBar1->SetStatusText("Stopped", 0); + _dhfsInstance.stop(); + break; + case DhfsInstanceState::STOPPED: + LibjvmWrapper::instance().setJavaHome(wxFileConfig::Get()->Read(kJavaHomeSettingsKey).ToStdString()); + m_statusText->SetLabel("Running"); + m_startStopButton->SetLabel("Stop"); + m_statusBar1->SetStatusText("Running", 0); + _dhfsInstance.start(wxFileConfig::Get()->Read(kMountPointSettingsKey).ToStdString(), { + + }); + break; + default: + throw Exception("Unhandled switch case"); + } +} + +void LauncherAppMainFrame::OnJavaHomeChanged(wxFileDirPickerEvent& event) { + wxFileConfig::Get()->Write(kJavaHomeSettingsKey, event.GetPath()); +} + +void LauncherAppMainFrame::OnMountPathChanged(wxFileDirPickerEvent& event) { + wxFileConfig::Get()->Write(kMountPointSettingsKey, event.GetPath()); } diff --git a/launcher/gui/src/LauncherAppMainFrame.h b/launcher/gui/src/LauncherAppMainFrame.h index 00bff7ae..b1d9605a 100644 --- a/launcher/gui/src/LauncherAppMainFrame.h +++ b/launcher/gui/src/LauncherAppMainFrame.h @@ -12,11 +12,18 @@ Subclass of MainFrame, which is generated by wxFormBuilder. #include "DhfsInstance.hpp" +static constexpr auto kJavaHomeSettingsKey = "DHFS/JavaHome"; +static constexpr auto kMountPointSettingsKey = "DHFS/MountDir"; + /** Implementing MainFrame */ class LauncherAppMainFrame : public MainFrame { protected: // Handlers for MainFrame events. - void OnStartStopButtonClick(wxCommandEvent& event); + void OnStartStopButtonClick(wxCommandEvent& event) override; + + void OnJavaHomeChanged(wxFileDirPickerEvent& event) override; + + void OnMountPathChanged(wxFileDirPickerEvent& event) override; public: /** Constructor */ diff --git a/launcher/gui/src/launcher.fbp b/launcher/gui/src/launcher.fbp index e65366a2..6c530334 100644 --- a/launcher/gui/src/launcher.fbp +++ b/launcher/gui/src/launcher.fbp @@ -50,7 +50,7 @@ 100,50 MainFrame - 500,300 + 499,341 wxDEFAULT_FRAME_STYLE ; ; forward_declare DHFS @@ -150,8 +150,8 @@ Info - 1 - + 0 + 1 1 1 @@ -203,16 +203,16 @@ wxTAB_TRAVERSAL - + bSizer2 wxVERTICAL none - + 5 - wxEXPAND + wxALL|wxEXPAND 1 - + wxID_ANY Status @@ -239,7 +239,7 @@ 5 1 0 - wxALL + wxALIGN_CENTER_VERTICAL|wxALL 0 1 @@ -280,7 +280,7 @@ 0 1 - m_staticText1 + m_statusText 1 @@ -384,7 +384,7 @@ 5 - wxEXPAND + wxALL|wxEXPAND 1 wxID_ANY @@ -460,7 +460,7 @@ Settings - 0 + 1 1 1 @@ -513,6 +513,490 @@ wxTAB_TRAVERSAL + + + bSizer5 + wxVERTICAL + none + + 5 + wxALL|wxEXPAND|wxFIXED_MINSIZE + 1 + + wxID_ANY + JVM + + sbSizer3 + wxVERTICAL + 1 + none + + 5 + wxEXPAND + 1 + + + wxBOTH + 1 + + 0 + + gbSizer2 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + + 5 + 1 + 3 + wxALL + 0 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + 0 + + + + + 1 + 0 + 1 + + 1 + + 0 + 0 + + Dock + 0 + Left + 0 + 1 + + 1 + + + 0 + 0 + wxID_ANY + Reset + + 0 + + 0 + + + 0 + + 1 + m_button2 + 1 + + + protected + 1 + + + + Resizable + 1 + + + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + 5 + 1 + 2 + wxEXPAND + 0 + 1 + + 0 + protected + 50 + + + + 5 + 1 + 1 + wxALL|wxEXPAND + 0 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + Select a folder + + 0 + + 1 + m_javaHomeDirPicker + 1 + + + protected + 1 + + Resizable + 1 + + wxDIRP_DEFAULT_STYLE|wxDIRP_USE_TEXTCTRL + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnJavaHomeChanged + + + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Java Home + 0 + + 0 + + + 0 + + 1 + m_staticText2 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + wxID_ANY + Paths + + sbSizer41 + wxVERTICAL + 1 + none + + 5 + wxEXPAND + 1 + + + wxBOTH + 1 + + 0 + + gbSizer3 + wxFLEX_GROWMODE_SPECIFIED + none + 0 + + 5 + 1 + 0 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + Mount path + 0 + + 0 + + + 0 + + 1 + m_staticText6 + 1 + + + protected + 1 + + Resizable + 1 + + + ; ; forward_declare + 0 + + + + + -1 + + + + 5 + 1 + 1 + wxALL|wxEXPAND + 0 + 1 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + Select a folder + + 0 + + 1 + m_mountPathDirPicker + 1 + + + protected + 1 + + Resizable + 1 + + wxDIRP_DEFAULT_STYLE|wxDIRP_USE_TEXTCTRL + ; ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnMountPathChanged + + + + + + + + + + + + Advanced Settings + 0 + + 1 + 1 + 1 + 1 + 0 + + 0 + 0 + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 0 + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_panel4 + 1 + + + protected + 1 + + Resizable + 1 + + ; ; forward_declare + 0 + + + + wxTAB_TRAVERSAL diff --git a/launcher/libjvm_wrapper/include_public/LibjvmWrapper.hpp b/launcher/libjvm_wrapper/include_public/LibjvmWrapper.hpp index fe008280..5dca76cf 100644 --- a/launcher/libjvm_wrapper/include_public/LibjvmWrapper.hpp +++ b/launcher/libjvm_wrapper/include_public/LibjvmWrapper.hpp @@ -6,19 +6,28 @@ #define LIBJVMWRAPPER_HPP #include +#include class LibjvmWrapper { public: static LibjvmWrapper& instance(); - decltype(JNI_CreateJavaVM)* WJNI_CreateJavaVM; + void setJavaHome(const std::string& javaHome); + + decltype(JNI_CreateJavaVM)* get_JNI_CreateJavaVM(); private: + void load(); + + void unload(); + LibjvmWrapper(); ~LibjvmWrapper(); - void* _lib_handle; + void* _lib_handle = nullptr; + decltype(JNI_CreateJavaVM)* WJNI_CreateJavaVM = nullptr; + std::string _java_home; }; diff --git a/launcher/libjvm_wrapper/src/LibjvmWrapper.cpp b/launcher/libjvm_wrapper/src/LibjvmWrapper.cpp index 72e02e41..775472bf 100644 --- a/launcher/libjvm_wrapper/src/LibjvmWrapper.cpp +++ b/launcher/libjvm_wrapper/src/LibjvmWrapper.cpp @@ -8,16 +8,24 @@ #include "Exception.h" -static constexpr auto LIBJVM_PATH = - "/Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home/lib/server/libjvm.dylib"; - LibjvmWrapper& LibjvmWrapper::instance() { static LibjvmWrapper instance; return instance; } LibjvmWrapper::LibjvmWrapper() { - _lib_handle = dlopen(LIBJVM_PATH, RTLD_NOW | RTLD_GLOBAL); +} + +void LibjvmWrapper::load() { + if (_java_home == "") + throw Exception("Java home not set"); + if (_lib_handle != nullptr) + throw Exception("load() called when already loaded"); + + std::string javaHomeAppended; + javaHomeAppended = _java_home + "/lib/server/libjvm.so"; + + _lib_handle = dlopen(javaHomeAppended.c_str(), RTLD_NOW | RTLD_GLOBAL); if (_lib_handle == nullptr) throw Exception(dlerror()); WJNI_CreateJavaVM = reinterpret_cast( @@ -26,6 +34,26 @@ LibjvmWrapper::LibjvmWrapper() { throw Exception(dlerror()); } -LibjvmWrapper::~LibjvmWrapper() { - dlclose(_lib_handle); +void LibjvmWrapper::unload() { + if (_lib_handle != nullptr) { + dlclose(_lib_handle); + _lib_handle = nullptr; + WJNI_CreateJavaVM = nullptr; + } +} + +decltype(JNI_CreateJavaVM)* LibjvmWrapper::get_JNI_CreateJavaVM() { + if (WJNI_CreateJavaVM == nullptr) { + load(); + } + return WJNI_CreateJavaVM; +} + +LibjvmWrapper::~LibjvmWrapper() { + unload(); +} + +void LibjvmWrapper::setJavaHome(const std::string& javaHome) { + unload(); + _java_home = javaHome; }