<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><br></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Sun, Dec 15, 2024 at 8:24 AM Ron Pressler <<a href="mailto:ron.pressler@oracle.com">ron.pressler@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
<br>
> On 14 Dec 2024, at 19:31, David Lloyd <<a href="mailto:david.lloyd@redhat.com" target="_blank">david.lloyd@redhat.com</a>> wrote:<br>
> <br>
> <br>
> I'm honestly baffled by your question, because it indicates that you probably haven't really read or understood the entirety of my message, though I tend to be pretty wordy so I acknowledge that I'm at least partially to blame if that is the case.<br>
<br>
<br>
Complaints related the configuration of the runtime are brought up from time to time. When I try to get to the bottom of the issue, people often get frustrated because they think the answer is obvious and I rarely get an answer.<br>
<br>
> You phrase the question as if users were being rebellious against some broadly accepted natural order of things, which does not reflect any reality that I or my colleagues are aware of. But to answer the question at exactly face value: the user typically doesn't even know the difference. Many users don't ever launch an application using the `java` launcher outside of university. They're running a Quarkus application, or deploying into WildFly or Tomcat, or launching via JBang, or running in Spring Boot, or maybe running a prepackaged application, or any one of dozens of other ways that an application can be packaged and deployed. A user doesn't usually have any idea about whether the class loader which loads their classes is setting them up as a named module or just defining classes the old fashioned way.<br>
<br>
<br>
Who is the user and what are the classes in this case?</blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">The user in this paragraph is the one launching the application.</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> For one, 99.99% of classes don’t need to care whether they reside in a named or an unnamed module.</blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I am not talking about these classes. Obviously `a = a + 6` doesn't care about modules or the lack thereof.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> For another, the application author does have full control over every JAR they list on the command to put it in a named or an unnamed module.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">No, they don't, because the users we are talking about are generally using a packaging solution of some sort. They have *some* control. They don't have *full* control unless they're ready to break things. It's like saying they have full control over what native libraries the JDK is using. It's *technically* true. But in practice they're not going to mess with low level stuff like that.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
But right now, I don’t think we’re talking about arbitrary libraries (or application classes). We’re not even talking about “regular" libraries that use a ServiceLoader.</blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">Yes, we are in fact talking about regular libraries, or at least, that's what I'm talking about: regular libraries which use ServiceLoader running within dynamic containers.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> We’re talking about “container” frameworks with a plugin system using ClassLoaders/ModuleLayer isolation. Such frameworks are important cornerstones of the ecosystem, but they make up maybe 1 in 10,000 libraries. It is only they who need to confront the class/module path decision.<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">We (container framework authors) generally don't use ServiceLoader for this kind of thing (well, we do sometimes, but that's not anywhere near my primary point of concern since we have full control over that code).</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Let’s call such a container framework X. There's at most one, maybe two, such frameworks in an application. Unless I misunderstand the situation, framework X — where the difficulty lies — is not itself loaded dynamically by WildFly or JBoss. Rather, it is loaded directly by the application (i.e. X *is* WildFly or JBoss). And here’s my question:<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I don't think this represents a correct understanding of the situation. If you were to write a server side application today, and you want access to some framework capability, you are most likely going to use e.g. CDI's `@Inject` and/or container-provided annotations for dependency injection. You are definitely not going to use ServiceLoader directly, because it has weird ergonomics, especially for end users, and as I said it is unpredictable within containers because it requires a knowledge of the class loading environment by the caller. For any practical purpose, ServiceLoader is going to be almost exclusively used by third-party libraries which are consumed by the user and wired up by the container.</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
To use X, the application author needs to configure the runtime (on the launcher command line) to load X.jar, where “X.jar" would typically stand for multiple service provider JARs. For some years, applications had to configure the runtime to load X like this `-cp X.jar`. You’re not complaining about that. But when I suggested you tell the application author to configure the runtime to load X with `-p X.jar` rather than `-cp X.jar` you seemed to claim that this is almost impossible and that `-cp X.jar` must also work. Why?<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">The application author is not using `-cp X.jar` or `-p X.jar` because in most cases, the application author is either not launching with Java at all (i.e. they're launching a container startup script), or they're going to launch an uberjar or some special launcher that sets up a class loading environment and bootstraps the application, following the instructions provided by the container (today this might just be e.g. `java -jar startup.jar` but again, in most cases this will be wrapped up in a script of some sort).</div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Is it because the application author would write `-cp X.jar` out of habit? Is it because the application author uses some build tool to construct the runtime configuration and is unable to tell the build tool to configure `-p X.jar`? I once asked a maintainer of such a framework this question and his answer was, “all my users are familiar with -cp, but many have not used -p before and I’m afraid they’ll find it weird/confusing.” Would that be your answer, too?<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">I've never heard that argument from our users, but our users are mostly running startup scripts or just following the directions given by our container documentation.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">> It's not really feasible to expect library authors to detect whether they are going to be run as a module or not, particularly if they have many entry points, as they sometimes do. They could for example add a run time check on every entry point, or on the class initializers of every entry point class.<br><br>
But this isn’t needed in 99% of cases, and we’re not talking about “library authors” in general. We’re talking about a handful of large (and important) frameworks. Even if such a framework doesn’t also provide the single entry point to the program, can’t you put the test in the same place you first create the ServiceLoader, which I expect would detect the misconfiguration quite early in a plugin-based framework?<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">You could, and that might work in many cases, maybe even most cases. Few third party library authors are going to do that though, especially if there isn't a standard blob of code to do that for them. Why would they? What is their motivation? As I said, they want their libraries to be ubiquitous, so I doubt you will be able to make me believe that they are going to want to exclude a class of users in the name of boosting module mode. Instead they will have the reasonable (based on documentation at least) expectation that ServiceLoader does something sensible always: specifically, that given some target environment, that it will find the implementation(s) of that service. But do refer to my other email about trying to work out the "correct" behavior of that class because it's not obvious.</div></div></div><span class="gmail_signature_prefix">-- </span><br><div dir="ltr" class="gmail_signature"><div dir="ltr">- DML • he/him<br></div></div></div>