RFR: Initial code for a JSON-based module descriptor.
Shi Jun Zhang
zhangshj at linux.vnet.ibm.com
Mon Apr 23 02:35:58 PDT 2012
On 4/19/2012 8:05 PM, David Bosschaert wrote:
> Following the discussion about module descriptor formats on jigsaw-dev
> and penrose-dev [1] I did an initial implementation that supports a
> JSON-based module descriptor.
>
> The JSON module descriptor is located inside the module in
> META-INF/module-info.json.
> The existing module-info.class file is still supported but if a
> module-info.json file is found this is used instead.
> I wrote a very small JSON parser, its class files are currently<
> 10kb, and it can possibly be made even smaller.
> Besides the unit tests _JSONParser and _ModuleInfoReader there is also
> a system-level test hello-json.sh that effectively compiles, installs
> and runs a small demo module with JSON metadata.
> For example module-info.json files see inside the hello-json.sh and
> module-info-reader.sh test scripts.
>
> Some other things to note:
> * Not all features of module-info.class are yet supported, this is
> just a starting point.
> * The fact that both module-info.class and module-info.json are
> supported side-by-side makes for some awkward code here and there.
> This should only be temporary.
> * The JSON parser is currently in the java.lang.module package, but
> it's pretty much general-purpose, so I guess it could be moved to a
> package like java.util or something like that.
>
> You can find the webrev here:
> http://cr.openjdk.java.net/~davidb/mijson/webrev.01/
>
> David
>
> [1] http://mail.openjdk.java.net/pipermail/penrose-dev/2012-April/000038.html
>
Hi David,
I get the following exception when i run the test you added.
chance at chance:~/workspace/penrose/jigsaw/jdk/test/org/openjdk/jigsaw/z.test$
../../../../../build/bin/java -L z.mlib -m com.greetings.json
Error occurred during initialization of VM
java.lang.InternalError: Recursive initialization of system class loader
at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1515)
at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1494)
at java.util.ServiceLoader.loadInstalled(ServiceLoader.java:618)
at
sun.util.LocaleServiceProviderPool$1.run(LocaleServiceProviderPool.java:131)
at java.security.AccessController.doPrivileged(Native Method)
at
sun.util.LocaleServiceProviderPool.<init>(LocaleServiceProviderPool.java:129)
at
sun.util.LocaleServiceProviderPool.getPool(LocaleServiceProviderPool.java:111)
at java.text.NumberFormat.getInstance(NumberFormat.java:747)
at java.text.NumberFormat.getNumberInstance(NumberFormat.java:407)
at java.util.Scanner.useLocale(Scanner.java:1231)
at java.util.Scanner.<init>(Scanner.java:585)
at java.util.Scanner.<init>(Scanner.java:608)
at java.lang.module.JSONParser.<init>(JSONParser.java:87)
at
java.lang.module.JSONModuleInfoReader.<init>(JSONModuleInfoReader.java:61)
at
java.lang.module.JSONModuleInfoReader.read(JSONModuleInfoReader.java:47)
at
java.lang.module.ModuleSystem.parseModuleInfoJSON(ModuleSystem.java:80)
at
org.openjdk.jigsaw.SimpleLibrary.findModuleDir(SimpleLibrary.java:763)
at
org.openjdk.jigsaw.SimpleLibrary.readLocalModuleInfoJSON(SimpleLibrary.java:855)
at org.openjdk.jigsaw.Library.readLocalModuleInfo(Library.java:142)
at org.openjdk.jigsaw.Catalog.readModuleView(Catalog.java:277)
at org.openjdk.jigsaw.Launcher.loadModule(Launcher.java:51)
at org.openjdk.jigsaw.Launcher.launch(Launcher.java:82)
at
java.lang.ClassLoader.initModularSystemClassLoader(ClassLoader.java:1557)
at java.lang.ClassLoader.initSystemClassLoader(ClassLoader.java:1522)
at java.lang.ClassLoader.getSystemClassLoader(ClassLoader.java:1494)
Can you verify whether you are using the latest code? As you just read
the whole json file into JSONParser, it's not necessary using the Scanner.
And some comments on the changes.
src/share/classes/java/lang/module/ModuleClassLoader.java
72 ModuleInfo mi;
73
74 // Weird: getResource/getResources() return matching files from all modules, even if not exported.
75 // URL miXML = getResource("/META-INF/module-info.xml");
76 URL miJSON = null;
77 try {
78 for (Enumeration<URL> infos = getResources("/META-INF/module-info.json"); infos.hasMoreElements(); ) {
79 URL info = infos.nextElement();
80 String suffix = id.name() + "/" + id.version().toString() + "/classes!/META-INF/module-info.json";
81 if (info.toExternalForm().endsWith(suffix)) {
82 miJSON = info;
83 break;
84 }
85 }
86 } catch (IOException e) {
87 throw new Error(e);
88 }
89
90 if (miJSON != null) {
91 try {
92 mi = moduleSystem.parseModuleInfoJSON(miJSON.openStream());
93 } catch (IOException e) {
94 throw new Error(e);
95 }
96 } else {
97 mi = moduleSystem.parseModuleInfo(bs);
98 }
ModuleClassLoader doesn't implement its own getResource() method so the
getResource invocation will call java.lang.ClassLoader.getResource and
it will delegate to parent's class loader first. I guess using
((org.openjdk.jigsaw.Loader)this).getResource("/META-INF/module-info.json")
will work. Although another method isModulePresent in ModuleClassLoader
also cast itself to org.openjdk.jigsaw.Loader, i don't think casting to
a subclass is a good design. A better way to solve this problem is that
not changing the defineModule method but adding a new method named
defineModuleByJSON which accepts JSON input stream. Then in
org.openjdk.jigsaw.Loader.findModule method, call defineModuleByJSON
method if module-info.json exists, else call defineModule method.
src/share/classes/java/lang/module/JSONParser.java
Line 152: jsonKeyValueList.charAt(i) is used for multiple times, assign
it to a local var.
The parser is pretty small but i am worried about the efficiency. The
more layers the JSON string has, more times the end part of the JSON
string will be parsed. For example,
{
"key1" :
{
"key2" :
{
"key3" : "value"
}
}
}
First time, it go through the whole string and find one key-value string
and then use regex to match "key1" and its value string. Second time, it
go through the string '"key2": { "key3" : "value" }' and find one
key-value string and then use regex to match "key2" and its value
string. Third time, it go through the string '"key3" : "value"' and find
one key-value string and then use regex to match "key3" and its value
"value". The performance degrades fast when the JSON structure becomes
complex.
Other changes look ok to me.
--
Regards,
Shi Jun Zhang
More information about the penrose-dev
mailing list