As mentioned in a previous message, I am creating universal macOS bundled
applications by including two Java runtimes in the application bundle, one for
arm and one for x86. The primary disadvantage of universal applications is
their size. For Java applications, there is an obvious opportunity to share the
class files, which are architecture neutral. In the current JDK, that would
mean sharing the lib/modules file, which would reduce the application size by
100MB or so.
This would be a no-brainer, except for one small detail: the lib/modules file
contains two class files that are different in the two runtimes.
These classes are PlatformProps (whose source is architecture-specific) and
Architecture (which inlines constants from PlatformProps). I presume the
motivation for this design is the performance improvement that results from the
compiler knowing the constant values. Is that correct?
It appears that these architecture-specific constants are used mostly, if not
exclusively, in jtreg and test programs. I tested this theory by replacing the
modules file in an arm runtime with the modules file from the corresponding x86
runtime. An application using this hybrid runtime started up normally. While
not an exhaustive test, the fact that it did not fall over dead is encouraging.
Another potential issue with sharing class files is that the module-info
classes in lib/modules identify the target architecture. My little experiment
suggests that this metadata is not used, but it would be nice to guarantee that.
It would good if sharing lib/modules was a supported feature, rather than just
hoping that it works and continues to work in the future.
I can see several possible options for supporting sharing of the lib/modules
file, based in part of how the above classes are used and how important the
inline performance gains are:
1. Split lib/modules into two files, one for architecture-specific class files
and one for architecture-independent class files.
2. Replace the inlining support with a conventional implementation that
initializes the constants using data obtained from a dynamic library.
3. Move the above classes into a test support module, one that jlink excludes
by default. If there are other clients of architecture related constants, they
can use conventional implementation classes, as described in the second option.
Thoughts?