8156142: ModuleReader instances don't always throw NPE for passed null args
authoralanb
Wed, 25 May 2016 20:12:32 +0100
changeset 38565 e97761823da2
parent 38564 8c49d605b024
child 38566 6a1386b76fdd
8156142: ModuleReader instances don't always throw NPE for passed null args Reviewed-by: chegar, mchung
jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java
jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java
jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java	Wed May 25 19:58:03 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java	Wed May 25 20:12:32 2016 +0100
@@ -30,6 +30,7 @@
 import java.io.InputStream;
 import java.net.URI;
 import java.nio.ByteBuffer;
+import java.util.Objects;
 import java.util.Optional;
 
 
@@ -163,9 +164,12 @@
      * @param  bb
      *         The byte buffer to release
      *
-     * @implSpec The default implementation does nothing.
+     * @implSpec The default implementation doesn't do anything except check
+     * if the byte buffer is null.
      */
-    default void release(ByteBuffer bb) { }
+    default void release(ByteBuffer bb) {
+        Objects.requireNonNull(bb);
+    }
 
     /**
      * Closes the module reader. Once closed then subsequent calls to locate or
--- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java	Wed May 25 19:58:03 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java	Wed May 25 20:12:32 2016 +0100
@@ -272,9 +272,9 @@
          * if not found.
          */
         private ImageLocation findImageLocation(String name) throws IOException {
+            Objects.requireNonNull(name);
             if (closed)
                 throw new IOException("ModuleReader is closed");
-
             if (imageReader != null) {
                 return imageReader.findLocation(module, name);
             } else {
@@ -322,6 +322,7 @@
 
         @Override
         public void release(ByteBuffer bb) {
+            Objects.requireNonNull(bb);
             ImageReader.releaseByteBuffer(bb);
         }
 
--- a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java	Wed May 25 19:58:03 2016 +0100
+++ b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java	Wed May 25 20:12:32 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReader;
 import java.lang.module.ModuleReference;
+import java.lang.reflect.Module;
 import java.net.URI;
 import java.net.URL;
 import java.net.URLConnection;
@@ -64,16 +65,24 @@
     private static final Path SRC_DIR    = Paths.get(TEST_SRC, "src");
     private static final Path MODS_DIR   = Paths.get("mods");
 
+    // the module name of the base module
+    private static final String BASE_MODULE = "java.base";
+
     // the module name of the test module
     private static final String TEST_MODULE = "m";
 
+    // resources in the base module
+    private static final String[] BASE_RESOURCES = {
+        "java/lang/Object.class"
+    };
+
     // resources in test module (can't use module-info.class as a test
     // resource as it will be modified by the jmod tool)
-    private static final String[] RESOURCES = {
+    private static final String[] TEST_RESOURCES = {
         "p/Main.class"
     };
 
-    // a resource that is not in the test module
+    // a resource that is not in the base or test module
     private static final String NOT_A_RESOURCE = "NotAResource";
 
 
@@ -89,7 +98,74 @@
 
 
     /**
-     * Test exploded module
+     * Test ModuleReader to module in runtime image
+     */
+    public void testImage() throws Exception {
+
+        ModuleFinder finder = ModuleFinder.ofSystem();
+        ModuleReference mref = finder.find(BASE_MODULE).get();
+        ModuleReader reader = mref.open();
+
+        try (reader) {
+
+            for (String name : BASE_RESOURCES) {
+                byte[] expectedBytes;
+                Module baseModule = Object.class.getModule();
+                try (InputStream in = baseModule.getResourceAsStream(name)) {
+                    expectedBytes = in.readAllBytes();
+                }
+
+                testFind(reader, name, expectedBytes);
+                testOpen(reader, name, expectedBytes);
+                testRead(reader, name, expectedBytes);
+
+            }
+
+            // test "not found"
+            assertFalse(reader.find(NOT_A_RESOURCE).isPresent());
+            assertFalse(reader.open(NOT_A_RESOURCE).isPresent());
+            assertFalse(reader.read(NOT_A_RESOURCE).isPresent());
+
+
+            // test nulls
+            try {
+                reader.find(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            try {
+                reader.open(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            try {
+                reader.read(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+            try {
+                reader.release(null);
+                assertTrue(false);
+            } catch (NullPointerException expected) { }
+
+        }
+
+        // test closed ModuleReader
+        try {
+            reader.open(BASE_RESOURCES[0]);
+            assertTrue(false);
+        } catch (IOException expected) { }
+
+
+        try {
+            reader.read(BASE_RESOURCES[0]);
+            assertTrue(false);
+        } catch (IOException expected) { }
+    }
+
+
+    /**
+     * Test ModuleReader to exploded module
      */
     public void testExplodedModule() throws Exception {
         test(MODS_DIR);
@@ -97,7 +173,7 @@
 
 
     /**
-     * Test modular JAR
+     * Test ModuleReader to modular JAR
      */
     public void testModularJar() throws Exception {
         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
@@ -111,7 +187,7 @@
 
 
     /**
-     * Test JMOD
+     * Test ModuleReader to JMOD
      */
     public void testJMod() throws Exception {
         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
@@ -145,7 +221,7 @@
         try (reader) {
 
             // test each of the known resources in the module
-            for (String name : RESOURCES) {
+            for (String name : TEST_RESOURCES) {
                 byte[] expectedBytes
                     = Files.readAllBytes(MODS_DIR
                         .resolve(TEST_MODULE)
@@ -157,6 +233,7 @@
             }
 
             // test "not found"
+            assertFalse(reader.find(NOT_A_RESOURCE).isPresent());
             assertFalse(reader.open(NOT_A_RESOURCE).isPresent());
             assertFalse(reader.read(NOT_A_RESOURCE).isPresent());
 
@@ -176,19 +253,22 @@
                 assertTrue(false);
             } catch (NullPointerException expected) { }
 
-            // should release(null) throw NPE?
+            try {
+                reader.release(null);
+                throw new RuntimeException();
+            } catch (NullPointerException expected) { }
 
         }
 
         // test closed ModuleReader
         try {
-            reader.open(RESOURCES[0]);
+            reader.open(TEST_RESOURCES[0]);
             assertTrue(false);
         } catch (IOException expected) { }
 
 
         try {
-            reader.read(RESOURCES[0]);
+            reader.read(TEST_RESOURCES[0]);
             assertTrue(false);
         } catch (IOException expected) { }
     }