Show splash-screen using standalone SWT in Equinox launcher#1279
Show splash-screen using standalone SWT in Equinox launcher#1279HannesWell wants to merge 2 commits into
Conversation
|
This pull request changes some projects for the first time in this development cycle. An additional commit containing all the necessary changes was pushed to the top of this PR's branch. To obtain these changes (for example if you want to push more changes) either fetch from your fork or apply the git patch. Git patchFurther information are available in Common Build Issues - Missing version increments. |
c6a8257 to
f610814
Compare
|
Did you measure how long it takes to show a Splash? JVM startup + class loading + SWT native library extraction + Display init might take similar compared to wait for the regular splash. In my removal of the native code the display of the splash felt laggy as it showed up after approx. a second. IIRC 400 ms are acceptable for showing a splash. Also I think SWT only supports one Display per process, which makes this approach harder. You would need to hand over the Display most likey the issue you are describing. |
Create the splash-screen immediately at application start-up using standalone SWT within the Equinox launcher, which is effectively a plain Java application with flat classpath. The SWT jars are obtained from the to be launched OSGi runtime but are loaded in this preliminary phase using a flat-classpath.
Yes I did a very simple measurement (using
In fact it depends on the platform how many displays are supported, at least on Windows it works on macOS it's forbidden and for Linux I don't know, maybe it depends on the distro. See e.g. also But yes this doesn't make it simpler. But this case is currently even more special since it loads the SWT jar twice with different classloaders and the native library at different locations (stand-alone extracts to the user-home, while in OSGi it is located in some Equinox specific areas). Loading to copies of the same native library from different locations prevents a complaint from the JVM that the native library is already loaded (this check is based on paths IIRC), but then later fails at runtime, which are probably the errors I currently encountered. I did some 'research' on this topic and asked the Gemini AI if two identical copies of a native library generally can be loaded with different classloaders and it negated it for the following conceptual reasons The complete conversationQuestion 1: Can a native library be loaded multiple times with multiple classloaders in Java?The short answer is no. In a standard Java Virtual Machine (JVM), a native library (like a If you attempt to load the same native library using a second classloader while the first one still "owns" it, the JVM will throw a rather grumpy Why the Restriction ExistsJava is a bit of a jealous partner when it comes to native code. This limitation isn't just a random rule; it’s a safeguard for the stability of your application.
The Error You'll SeeIf you try to load a library that is already linked elsewhere, you’ll encounter an error that looks something like this:
How to Work Around ItIf you find yourself in a situation where multiple parts of your application (perhaps different plugins or modules) need access to the same native library, you generally have two paths:
A Modern Note on JNIWhile the above holds true for standard JNI (Java Native Interface), some modern frameworks and newer versions of the JDK have explored ways to make native interop more flexible, but the core "one library, one classloader" rule remains the standard behavior for safety. If you're dealing with a complex modular system (like OSGi), this is often the #1 headache developers face, so centralizing that native load is usually your best bet. Question 2: Does this rule apply if I load an exact copy of a native library at a different location through another classloader?Technically, you might bypass the "already loaded" check if the file paths are different, but you will almost certainly crash or fail during the linking phase. Even if you make an exact copy of the library and put it in a different directory, the JVM and the underlying Operating System (OS) still have to deal with the Global Symbol Table. 1. The "Symbol Collision" WallNative libraries aren't just files; they are bundles of named functions (symbols). When the JVM loads a library to support a If you load two copies of the library:
When Classloader B tries to link its Java methods, the JVM sees that the symbol 2. The Static State DisasterSuppose you found a way to trick the JVM into loading both (perhaps by renaming the internal symbols, which is a massive chore). You would then run into Native Memory Corruption. Most native libraries (C/C++) use
Since they are running in the same process memory space, they aren't actually isolated. They will fight over the same memory addresses, leading to "Heisenbugs" or immediate segmentation faults. Is there any way to make this work?If you truly need multiple versions of the same native logic running simultaneously, you have two real options:
Does your use case involve running two different versions of the same library, or are you trying to isolate two different plugins? The proposed resolution for this problem to use process isolation and to launch a sub-process instead sounds reasonable. On the other hand, this would avoid the need to pass a shell-handle and maybe even makes the Of course this then requires adaption of the WorkbenchPlugin. I plan to investigate the sub-process approach further. If SWT does not use JNI at some point in the future (and only FFM), we could explore again if running the splash from the same JVM with two classloaders works. |
8397064 to
7dc8612
Compare
|
400 ms or 500 ms sounds great for a splash screen. What about starting it in the OSGI instance that later loads the rest of the app? This way you would have to load SWT only once. For workbench I already had a patch for my removal of the splash screen which replaced Shell.internal_new() factory and was IMHO a nice general enhancement. But giving the expressed overload of the community with to many changes, I through it away. Rough implementation idea was: |
Create the splash-screen immediately at application start-up using standalone SWT within the Equinox launcher, which is effectively a plain Java application with flat classpath.
The SWT jars are obtained from the to be launched OSGi runtime but are loaded in this preliminary phase using a flat-classpath.
Fixes
This is currently a draft because, although showing the splash-screen works as desired, the launched application has a severely broken UI, at least under Windows. But at least it launches...
It's probably an interference of the
Displaycreated within the launcher and the display created within the OSGi runtime. E.g. disposing the launchers display, crashes the entire application and just creating the display without using it further causes the UI break. But I have high hopes that this can be fixed eventually.It would be interesting for me how the situation is under Linux and macOS.
If anybody who has these OS at hand could check this out and just launch an Eclipse application containing e.g. the
o.e.sdkit would be interesting if the application starts at all and what the state of the UI is.