Loading classes and resources in Java 9

醉酒当歌 提交于 2019-12-28 12:55:33

问题


I was reading this article on InfoQ quoting Reinhold:

Developers can still use the Java class path in Java 9 for the Java runtime to search for classes and resource files. It's just that with Java 9's modules, developers no longer need the class path.

So now my question is: what is the proper Java 9 way to do the tasks listed above? How do you dynamically load e.g. an image (short of fiddling with relative paths)?

Even more interestingly, how would one check if a class is available and make a decision dynamically (e.g. check if Jackson is available and, if so, use it for JSON serialization and if not use something else)?

The article also mentions Spring Boot already supporting Java 9, and Spring Boot definitely does a lot of dynamic loading. So maybe someone knows the priece of code from Spring that I can look at?


回答1:


First, to set the record straight, I neither said nor wrote the text quoted above. I’d never have put it that way. That’s just sloppy reporting on the part of the publications involved.

The most important thing to understand about class loading and resource lookup in Java 9 is that, at a fundamental level, they have not changed. You can search for classes and resources in the same way that you always have, by invoking Class::forName and the various getResource* methods in the Class and ClassLoader classes, regardless of whether your code is loaded from the class path or the module path. There are still three built-in class loaders, just as there were in JDK 1.2, and they have the same delegation relationships. Lots of existing code therefore just works, out-of-the-box.

There are some nuances, as noted in JEP 261: The concrete type of the built-in class loaders has changed, and some classes formerly loaded by the bootstrap class loader are now loaded by the platform class loader in order to improve security. Existing code which assumes that a built-in class loader is a URLClassLoader, or that a class is loaded by the bootstrap class loader, may therefore require minor adjustments.

A final important difference is that non-class-file resources in a module are encapsulated by default, and hence cannot be located from outside the module unless their effective package is open. To load resources from your own module it’s best to use the resource-lookup methods in Class or Module, which can locate any resource in your module, rather than those in ClassLoader, which can only locate non-class-file resources in the open packages of a module.




回答2:


[Edit: this answer was written prior to Mark's authoritative answer. I've revised mine to provide a simple example, available on GitHub.]

Per this video, class loading in Java 9 is unchanged.

As an example, let's say we have:

  • an example.jar that contains an image in the package net.codetojoy.example.resources
  • to beef up the jar, net.codetojoy.example.Composer is public (and exported, where applicable)
  • a simple App class that uses example.jar as a library and attempts to load the image from it

The relevant code in App:

static InputStream getResourceAsStream(String resource) 
    throws Exception {

    // Load net/codetojoy/example/resource/image.jpg
    // Assume net.codetojoy.example.Composer is public/exported
    // resource is 'resource/image.jpg'

    InputStream result = Composer.class.getResourceAsStream(resource);

    return result;
}   

Here are a few cases for example.jar in JDK 9:

Old-Fashioned, Non-Modular Jar

If example.jar is not a module, the code just works. Class loading is unchanged.

Modular Jar With Open Package

In this case, this is the module-info.java file:

module net.codetojoy.example {
    // export the Composer class
    exports net.codetojoy.example;

    // image is available
    opens net.codetojoy.example.resources;
}

In this case, the image can be loaded by the client, because the package is open.

Modular Jar Without Open Package

In this case, module-info.java is:

module net.codetojoy.example {
    // export the Composer class
    exports net.codetojoy.example;

    // package not opened: image not available
    // opens net.codetojoy.example.resources;
}

In this case, the image cannot be loaded, because of strong encapsulation: the module is protecting the image by not opening the package.

Full source here on GitHub.



来源:https://stackoverflow.com/questions/45166757/loading-classes-and-resources-in-java-9

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!