Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I bundle a JRE into an EXE for a Java Application? Launch4j says "runtime is missing or corrupted."

I am new to programming in Java but am generally familiar with how everything works. I would like to be able to put both a jar file and a jre into a windows executable(exe) so that when I distribute it, the client needn't have a JRE installed. What program should I use?

I have launch4j and it seems to do exactly what I want but when I try to run the app, I get "This application was configured to use a bundled Java Runtime Environment but the runtime is missing or corrupted."

I want my app to just be a runnable exe, not an installer. At the very least, can anyone show me how to correctly bundle a JRE with launch4j?

like image 687
MagicGuy52 Avatar asked Dec 21 '12 20:12

MagicGuy52


People also ask

Can Java EXE run without JRE?

You cannot do without JRE.


3 Answers

The only way I could bundle a JRE was to use Launch4J and Inno Setup Compiler.

First, create a jre6 folder (for example) in the same directory as your output file (.exe).

Then copy the JRE from your system into your jre6 folder.

Then you open Launch4J and set the Bundled JRE path - just type in jre6. Then click the Build button (obviously, after you've entered all the other parameters - but the only value you need to enter on the JRE tab itself is the Bundled JRE path value.)

I would have expected that to work, but if you then move the .exe to a new location (so it is no longer co-located with your jre6 folder) you get the This application was configured to use a bundled Java Runtime Environment but the runtime is missing or corrupted error when you try to run the application...

I've been playing around with this all day and there was no way I could get Launch4J to include the JRE in the .exe file. Really poor in my opinion, as their documentation does not seem to allude to this issue at all.

So what I did to solve was to use Inno Setup Compiler (ISC). This app is used to wrap your .exe as a Windows Installer file. So I added a setting to the ISC script that copies the JRE into the installer package. The line I added to the script (in the [Files] section) was:

Source: "M:\Netbeans\MyApp\jre6\*"; DestDir: "{app}\jre6\"; Flags: recursesubdirs createallsubdirs 

...a bit of workaround, but it did the trick.

Repeat all the above steps, and you should be sorted.

like image 129
ban-geoengineering Avatar answered Sep 25 '22 02:09

ban-geoengineering


the easy method to package jre to exe that lanch4j packaged is use wrap.

warp-packer --arch windows-x64 --input_dir mycrt --exec run.bat --output single.exe 

and then stop cmd windows when launch exe.

editbin /subsystem:windows 

warp: https://github.com/dgiagio/warp

editbin: installed by VS

Demo:

enter image description here

enter image description here

like image 39
jamlee Avatar answered Sep 23 '22 02:09

jamlee


Bundled JRE Solution for Inno Setup

In order to implement a bundled JRE solution with an application jar, I created an Inno Setup script that:

1) copies the JRE into the install exe

2) executes the equivalent of terminal command: java -jar myjar.jar using the bundled JRE

Firstly I copy the JRE:

#define MyJREPath "C:\Program Files\Java\jre1.8.0_191"

[Files]
Source: "{#MyJREPath}\*"; DestDir: "{app}\runtime\jre\";  \
        Flags: ignoreversion recursesubdirs createallsubdirs;  

I follow the directory structure convention shown here: https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/self-contained-packaging.html

To run the equivalent of java -jar myjar.jar:

[Run]
Filename: "{app}\runtime\jre\bin\javaw.exe"; Parameters: " -jar myjar.jar"; \
          WorkingDir: "{app}\app\"; \
          Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; \
          Flags: postinstall skipifsilent   

(n.b. java.exe runs with a terminal and javaw.exe runs without a terminal)

Desktop shortcut needs to have the right filename, parameters and working directory:

[Icons]
Name: "{commondesktop}\{#MyAppName}"; \
      IconFilename: "{app}\app\{#MyAppIcoName}"; \
      Filename: "{app}\runtime\jre\bin\javaw.exe"; \
      Parameters: " -jar myjar.jar"; \
      WorkingDir: "{app}\app\"; \
      Tasks: desktopicon

[Tasks]
Name: "desktopicon"; \
    Description: "{cm:CreateDesktopIcon}"; \
    GroupDescription: "{cm:AdditionalIcons}"; \
    Flags: unchecked

For the icing on the cake, in order make my script handle both bundled JRE and none bundled options I use the Preprocessor IF statement (duplicated in each script section) to test whether the script has an empty MyJREPath or not. If MyJREPath is not empty and so a bundled JRE solution is required I use the coding above; alternatively if a bundled solution is not required then I use more "normal" coding shown the Inno Setup examples or generated by their wizard. Here's the IF statement:

#if MyJREPath != ""
    ; bundled JRE required

#else
    ; bundled JRE not required
#endif

Here's most of my script put together:

        ; Script generated by the Inno Setup Script Wizard.
        ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!


        ; some more #defines here

        #define MyAppExeName "javaw.exe"
        #define MyJREPath "C:\Program Files\Java\jre1.8.0_191" 
        ;#define MyJREPath ""




        [Setup]
        ; NOTE: The value of AppId uniquely identifies this application.
        ; Do not use the same AppId value in installers for other applications.
        ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
        AppId=XXXXXXXXXX
        AppName={#MyAppName}
        AppVersion={#MyAppVersion}
        ;AppVerName={#MyAppName} {#MyAppVersion}
        AppPublisher={#MyAppPublisher}
        DefaultGroupName={#MyAppPublisher}
        AppPublisherURL={#MyAppURL}
        AppSupportURL={#MyAppURL}
        AppUpdatesURL={#MyAppURL}   
        DefaultDirName={pf}\{#MyDefaultDirName}
        DisableProgramGroupPage=yes
        LicenseFile={#MyInnoSetupDir}\system\{#MyLicenseFile}
        OutputDir={#MyInnoSetupDir}

        #if MyJREPath != "" 
          ; run app with bundled JRE
          OutputBaseFilename={#MyAppName}-{#MyAppVersion}-bundledJRE-setup
        #else
          ; run app without bundled JRE
          OutputBaseFilename={#MyAppName}-{#MyAppVersion}-setup          
        #endif 

        SetupIconFile={#MyInnoSetupDir}\{#MyAppIcoName}
        Compression=lzma
        SolidCompression=yes  
        AppComments={#MyAppName}
        AppCopyright={#MyAppCopyright}  
        UninstallDisplayIcon={#MyInnoSetupDir}\{#MyAppIcoName}
        UninstallDisplayName={#MyAppName}
        WizardImageStretch=No
        WizardSmallImageFile={#MyInnoSetupDir}\{#MyAppBmpName}



        [Languages]
        Name: "english"; MessagesFile: "compiler:Default.isl"
        ;Name: "german"; MessagesFile: "compiler:Languages\German.isl"

        [Tasks]
        Name: "desktopicon"; \
                Description: "{cm:CreateDesktopIcon}"; \
                GroupDescription: "{cm:AdditionalIcons}"; \
                Flags: unchecked
        Name: "quicklaunchicon"; \
                Description: "{cm:CreateQuickLaunchIcon}"; \
                GroupDescription: "{cm:AdditionalIcons}"; \
                Flags: unchecked; OnlyBelowVersion: 0,6.1

        [Files]
        ; bundle JRE if required
        #if MyJREPath != "" 
            Source: "{#MyJREPath}\*"; DestDir: "{app}\runtime\jre\";  \
                Flags: ignoreversion recursesubdirs createallsubdirs;       
        #endif      

        ; copy jar and all files  
        Source: "{#MyInnoSetupDir}\*"; DestDir: "{app}\app\"; \        
                Flags: ignoreversion recursesubdirs createallsubdirs


        [Icons]
        #if MyJREPath != ""
          ; set up icons with bundled JRE
          Name: "{commonprograms}\{#MyAppName}"; \
                  IconFilename: "{app}\app\{#MyAppIcoName}"; \
                  Filename: "{app}\runtime\jre\bin\{#MyAppExeName}"; \
                  Parameters: " -jar {#MyJarName}"; \
                  WorkingDir: "{app}\app\"
          Name: "{commondesktop}\{#MyAppName}"; \
                  IconFilename: "{app}\app\{#MyAppIcoName}"; \
                  Filename: "{app}\runtime\jre\bin\{#MyAppExeName}"; \
                  Parameters: " -jar {#MyJarName}"; \
                  WorkingDir: "{app}\app\"; \
                  Tasks: desktopicon            
          Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; \
                  IconFilename: "{app}\app\{#MyAppIcoName}"; \
                  Filename: "{app}\runtime\jre\bin\{#MyAppExeName}"; \
                  Parameters: " -jar {#MyJarName}"; \
                  WorkingDir: "{app}\app\"; \
                  Tasks: quicklaunchicon
        #else
          ; set up icons without bundled JRE
          Name: "{commonprograms}\{#MyAppName}"; \
                  IconFilename: "{app}\app\{#MyAppIcoName}"; \
                  Filename: "{app}\app\{#MyJarName}"; \
                  WorkingDir: "{app}\app\"
          Name: "{commondesktop}\{#MyAppName}"; \
                  IconFilename: "{app}\app\{#MyAppIcoName}"; \
                  Filename: "{app}\app\{#MyJarName}"; \
                  WorkingDir: "{app}\app\"; \
                  Tasks: desktopicon            
          Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\{#MyAppName}"; \
                  IconFilename: "{app}\app\{#MyAppIcoName}"; \
                  Filename: "{app}\app\{#MyJarName}"; \
                  WorkingDir: "{app}\app\"; \
                  Tasks: quicklaunchicon 
        #endif

        [Run]
        #if MyJREPath != ""
          ; run app with bundled JRE
          Filename: "{app}\runtime\jre\bin\{#MyAppExeName}"; Parameters: " -jar {#MyJarName}"; \
                  WorkingDir: "{app}\app\"; \
                  Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; \
                  Flags: postinstall skipifsilent          
        #else
          ; run app without bundled JRE
          Filename: "{app}\app\{#MyJarName}"; \
                  WorkingDir: "{app}\app\"; \
                  Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; \
                  Flags: shellexec postinstall skipifsilent          
        #endif 

Hope this helps.

like image 43
David Miller Avatar answered Sep 26 '22 02:09

David Miller