Path: blob/master/test/jdk/sun/security/provider/FileInputStreamPool/FileInputStreamPoolTest.java
41154 views
/*1* Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 804776926* @modules java.base/java.io:open27* java.base/java.lang.ref:open28* java.base/sun.security.provider:open29* @summary SecureRandom should be more frugal with file descriptors30*/3132import java.io.File;33import java.io.FileDescriptor;34import java.io.FileInputStream;35import java.io.FileOutputStream;36import java.io.FilterInputStream;37import java.io.IOException;38import java.io.InputStream;39import java.lang.ref.Reference;40import java.lang.ref.ReferenceQueue;41import java.lang.ref.WeakReference;42import java.lang.reflect.Field;43import java.lang.reflect.InvocationTargetException;44import java.lang.reflect.Method;45import java.lang.reflect.UndeclaredThrowableException;46import java.util.Arrays;47import java.util.HashSet;4849public class FileInputStreamPoolTest {5051static final byte[] bytes = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};5253static FilterInputStream testCaching(File file) throws IOException {54InputStream in1 = TestProxy.FileInputStreamPool_getInputStream(file);55InputStream in2 = TestProxy.FileInputStreamPool_getInputStream(file);56assertTrue(in1 == in2,57"1st InputStream: " + in1 +58" is not same as 2nd: " + in2);5960byte[] readBytes = new byte[bytes.length];61int nread = in1.read(readBytes);62assertTrue(bytes.length == nread,63"short read: " + nread +64" bytes of expected: " + bytes.length);65assertTrue(Arrays.equals(readBytes, bytes),66"readBytes: " + Arrays.toString(readBytes) +67" not equal to expected: " + Arrays.toString(bytes));6869return (FilterInputStream)in1;70}7172static void assertTrue(boolean test, String message) {73if (!test) {74throw new AssertionError(message);75}76}7778static void processReferences(FilterInputStream in1) throws InterruptedException, IOException {79FileInputStream fis = TestProxy.FilterInputStream_getInField(in1);80FileDescriptor fd = fis.getFD();81System.out.printf("fis: %s, fd: %s%n", fis, fd);82// Prepare to wait for FD to be reclaimed83ReferenceQueue<Object> queue = new ReferenceQueue<>();84HashSet<Reference<?>> pending = new HashSet<>();85pending.add(new WeakReference<>(in1, queue));86pending.add(new WeakReference<>(fis, queue));87pending.add(new WeakReference<>(fd, queue));8889Reference<?> r;90while (((r = queue.remove(10L)) != null)91|| !pending.isEmpty()) {92System.out.printf("r: %s, pending: %d%n", r, pending.size());93if (r != null) {94pending.remove(r);95} else {96fd = null;97fis = null;98in1 = null;99System.gc(); // attempt to reclaim the FD100}101Thread.sleep(10L);102}103Reference.reachabilityFence(fd);104Reference.reachabilityFence(fis);105Reference.reachabilityFence(in1);106}107108public static void main(String[] args) throws Exception {109// 1st create temporary file110File file = File.createTempFile("test", ".dat");111try (AutoCloseable acf = () -> {112// On Windows, failure to delete file is probably a consequence113// of the file still being opened - so the test should fail.114assertTrue(file.delete(),115"Can't delete: " + file + " (is it still open?)");116}) {117try (FileOutputStream out = new FileOutputStream(file)) {118out.write(bytes);119}120121// test caching 1st time122123processReferences(testCaching(file));124125// test caching 2nd time - this should only succeed if the stream126// is re-opened as a consequence of cleared WeakReference127128processReferences(testCaching(file));129}130}131132/**133* A proxy for (package)private static methods:134* sun.security.provider.FileInputStreamPool.getInputStream135* java.lang.ref.Reference.waitForReferenceProcessing136*/137static class TestProxy {138private static final Method getInputStreamMethod;139private static final Method waitForReferenceProcessingMethod;140private static final Field inField;141142static {143try {144Class<?> fileInputStreamPoolClass =145Class.forName("sun.security.provider.FileInputStreamPool");146getInputStreamMethod =147fileInputStreamPoolClass.getDeclaredMethod(148"getInputStream", File.class);149getInputStreamMethod.setAccessible(true);150151waitForReferenceProcessingMethod =152Reference.class.getDeclaredMethod("waitForReferenceProcessing");153waitForReferenceProcessingMethod.setAccessible(true);154155inField = FilterInputStream.class.getDeclaredField("in");156inField.setAccessible(true);157} catch (Exception e) {158throw new Error(e);159}160}161162static InputStream FileInputStreamPool_getInputStream(File file)163throws IOException {164try {165return (InputStream) getInputStreamMethod.invoke(null, file);166} catch (InvocationTargetException e) {167Throwable te = e.getTargetException();168if (te instanceof IOException) {169throw (IOException) te;170} else if (te instanceof RuntimeException) {171throw (RuntimeException) te;172} else if (te instanceof Error) {173throw (Error) te;174} else {175throw new UndeclaredThrowableException(te);176}177} catch (IllegalAccessException e) {178throw new RuntimeException(e);179}180}181182static boolean Reference_waitForReferenceProcessing() {183try {184return (boolean) waitForReferenceProcessingMethod.invoke(null);185} catch (InvocationTargetException e) {186Throwable te = e.getTargetException();187if (te instanceof InterruptedException) {188return true;189} else if (te instanceof RuntimeException) {190throw (RuntimeException) te;191} else if (te instanceof Error) {192throw (Error) te;193} else {194throw new UndeclaredThrowableException(te);195}196} catch (IllegalAccessException e) {197throw new RuntimeException(e);198}199}200201static FileInputStream FilterInputStream_getInField(FilterInputStream fis) {202try {203return (FileInputStream) inField.get(fis);204} catch (IllegalAccessException e) {205throw new RuntimeException(e);206}207}208}209}210211212