author | rriggs |
Fri, 23 Feb 2018 14:26:29 -0500 | |
changeset 48941 | 4f11514fe783 |
parent 48534 | 12d9ff9e0a4b |
child 50727 | 081b132c4dc0 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
48534 | 2 |
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. |
|
8 |
* |
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
13 |
* accompanied this code). |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License version |
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 |
* |
|
5506 | 19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 |
* or visit www.oracle.com if you need additional information or have any |
|
21 |
* questions. |
|
2 | 22 |
*/ |
23 |
||
24 |
/** |
|
25 |
* |
|
26 |
* @test |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
27 |
* @modules java.base/java.io:open |
2 | 28 |
* @bug 6524062 |
29 |
* @summary Test to ensure that FIS.finalize() invokes the close() method as per |
|
30 |
* the specification. |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
31 |
* @run main/othervm UnreferencedFISClosesFd |
2 | 32 |
*/ |
33 |
import java.io.File; |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
34 |
import java.io.FileDescriptor; |
2 | 35 |
import java.io.FileInputStream; |
36 |
import java.io.FileNotFoundException; |
|
37 |
import java.io.IOException; |
|
48534 | 38 |
import java.lang.management.ManagementFactory; |
39 |
import java.lang.management.OperatingSystemMXBean; |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
40 |
import java.lang.ref.Reference; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
41 |
import java.lang.ref.ReferenceQueue; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
42 |
import java.lang.ref.WeakReference; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
43 |
import java.lang.reflect.Field; |
48941 | 44 |
import java.nio.file.Files; |
45 |
import java.nio.file.Path; |
|
46 |
import java.nio.file.Paths; |
|
47 |
import java.util.ArrayDeque; |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
48 |
import java.util.HashSet; |
48941 | 49 |
import java.util.List; |
50 |
import java.util.Optional; |
|
51 |
import java.util.concurrent.TimeUnit; |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
52 |
import java.util.concurrent.atomic.AtomicInteger; |
2 | 53 |
|
48534 | 54 |
import com.sun.management.UnixOperatingSystemMXBean; |
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
55 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
56 |
/** |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
57 |
* Tests for FIS unreferenced. |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
58 |
* - Not subclassed - cleaner cleanup |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
59 |
* - Subclassed no finalize or close - cleaner cleanup |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
60 |
* - Subclassed close overridden - AltFinalizer cleanup |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
61 |
* - Subclasses finalize overridden - cleaner cleanup |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
62 |
* - Subclasses finalize and close overridden - AltFinalizer cleanup |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
63 |
*/ |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
64 |
public class UnreferencedFISClosesFd { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
65 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
66 |
enum CleanupType { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
67 |
CLOSE, // Cleanup is handled via calling close |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
68 |
CLEANER} // Cleanup is handled via Cleaner |
2 | 69 |
|
70 |
static final String FILE_NAME = "empty.txt"; |
|
71 |
||
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
72 |
/** |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
73 |
* Subclass w/ no overrides; not finalize or close. |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
74 |
* Cleanup should be via the Cleaner (not close). |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
75 |
*/ |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
76 |
public static class StreamOverrides extends FileInputStream { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
77 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
78 |
protected final AtomicInteger closeCounter; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
79 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
80 |
public StreamOverrides(String name) throws FileNotFoundException { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
81 |
super(name); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
82 |
closeCounter = new AtomicInteger(0); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
83 |
} |
2 | 84 |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
85 |
final AtomicInteger closeCounter() { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
86 |
return closeCounter; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
87 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
88 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
89 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
90 |
/** |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
91 |
* Subclass overrides close. |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
92 |
* Cleanup should be via AltFinalizer calling close(). |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
93 |
*/ |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
94 |
public static class StreamOverridesClose extends StreamOverrides { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
95 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
96 |
public StreamOverridesClose(String name) throws FileNotFoundException { |
2 | 97 |
super(name); |
98 |
} |
|
99 |
||
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
100 |
public void close() throws IOException { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
101 |
closeCounter.incrementAndGet(); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
102 |
super.close(); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
103 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
104 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
105 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
106 |
/** |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
107 |
* Subclass overrides finalize. |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
108 |
* Cleanup should be via the Cleaner (not close). |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
109 |
*/ |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
110 |
public static class StreamOverridesFinalize extends StreamOverrides { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
111 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
112 |
public StreamOverridesFinalize(String name) throws FileNotFoundException { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
113 |
super(name); |
2 | 114 |
} |
115 |
||
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
116 |
@SuppressWarnings({"deprecation","removal"}) |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
117 |
protected void finalize() throws IOException { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
118 |
super.finalize(); |
2 | 119 |
} |
120 |
} |
|
121 |
||
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
122 |
/** |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
123 |
* Subclass overrides finalize and close. |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
124 |
* Cleanup should be via AltFinalizer calling close(). |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
125 |
*/ |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
126 |
public static class StreamOverridesFinalizeClose extends StreamOverridesClose { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
127 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
128 |
public StreamOverridesFinalizeClose(String name) throws FileNotFoundException { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
129 |
super(name); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
130 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
131 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
132 |
@SuppressWarnings({"deprecation","removal"}) |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
133 |
protected void finalize() throws IOException { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
134 |
super.finalize(); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
135 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
136 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
137 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
138 |
/** |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
139 |
* Main runs each test case and reports number of failures. |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
140 |
*/ |
2 | 141 |
public static void main(String argv[]) throws Exception { |
142 |
||
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
143 |
File inFile = new File(System.getProperty("test.dir", "."), FILE_NAME); |
2 | 144 |
inFile.createNewFile(); |
145 |
inFile.deleteOnExit(); |
|
146 |
||
147 |
String name = inFile.getPath(); |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
148 |
|
48534 | 149 |
long fdCount0 = getFdCount(); |
150 |
System.out.printf("initial count of open file descriptors: %d%n", fdCount0); |
|
151 |
||
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
152 |
int failCount = 0; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
153 |
failCount += test(new FileInputStream(name), CleanupType.CLEANER); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
154 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
155 |
failCount += test(new StreamOverrides(name), CleanupType.CLEANER); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
156 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
157 |
failCount += test(new StreamOverridesClose(name), CleanupType.CLOSE); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
158 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
159 |
failCount += test(new StreamOverridesFinalize(name), CleanupType.CLEANER); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
160 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
161 |
failCount += test(new StreamOverridesFinalizeClose(name), CleanupType.CLOSE); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
162 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
163 |
if (failCount > 0) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
164 |
throw new AssertionError("Failed test count: " + failCount); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
165 |
} |
48534 | 166 |
|
167 |
// Check the final count of open file descriptors |
|
168 |
long fdCount = getFdCount(); |
|
169 |
System.out.printf("final count of open file descriptors: %d%n", fdCount); |
|
170 |
if (fdCount != fdCount0) { |
|
48941 | 171 |
listProcFD(); |
48534 | 172 |
throw new AssertionError("raw fd count wrong: expected: " + fdCount0 |
173 |
+ ", actual: " + fdCount); |
|
174 |
} |
|
175 |
} |
|
176 |
||
177 |
// Get the count of open file descriptors, or -1 if not available |
|
178 |
private static long getFdCount() { |
|
179 |
OperatingSystemMXBean mxBean = ManagementFactory.getOperatingSystemMXBean(); |
|
180 |
return (mxBean instanceof UnixOperatingSystemMXBean) |
|
181 |
? ((UnixOperatingSystemMXBean) mxBean).getOpenFileDescriptorCount() |
|
182 |
: -1L; |
|
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
183 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
184 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
185 |
private static int test(FileInputStream fis, CleanupType cleanType) throws Exception { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
186 |
|
2 | 187 |
try { |
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
188 |
System.out.printf("%nTesting %s%n", fis.getClass().getName()); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
189 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
190 |
// Prepare to wait for FIS to be reclaimed |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
191 |
ReferenceQueue<Object> queue = new ReferenceQueue<>(); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
192 |
HashSet<Reference<?>> pending = new HashSet<>(); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
193 |
WeakReference<FileInputStream> msWeak = new WeakReference<>(fis, queue); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
194 |
pending.add(msWeak); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
195 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
196 |
FileDescriptor fd = fis.getFD(); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
197 |
WeakReference<FileDescriptor> fdWeak = new WeakReference<>(fd, queue); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
198 |
pending.add(fdWeak); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
199 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
200 |
Field fdField = FileDescriptor.class.getDeclaredField("fd"); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
201 |
fdField.setAccessible(true); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
202 |
int ffd = fdField.getInt(fd); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
203 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
204 |
Field altFinalizerField = FileInputStream.class.getDeclaredField("altFinalizer"); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
205 |
altFinalizerField.setAccessible(true); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
206 |
Object altFinalizer = altFinalizerField.get(fis); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
207 |
if ((altFinalizer != null) ^ (cleanType == CleanupType.CLOSE)) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
208 |
throw new RuntimeException("Unexpected AltFinalizer: " + altFinalizer |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
209 |
+ ", for " + cleanType); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
210 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
211 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
212 |
Field cleanupField = FileDescriptor.class.getDeclaredField("cleanup"); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
213 |
cleanupField.setAccessible(true); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
214 |
Object cleanup = cleanupField.get(fd); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
215 |
System.out.printf(" cleanup: %s, alt: %s, ffd: %d, cf: %s%n", |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
216 |
cleanup, altFinalizer, ffd, cleanupField); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
217 |
if ((cleanup != null) ^ (cleanType == CleanupType.CLEANER)) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
218 |
throw new Exception("unexpected cleanup: " |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
219 |
+ cleanup + ", for " + cleanType); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
220 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
221 |
if (cleanup != null) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
222 |
WeakReference<Object> cleanupWeak = new WeakReference<>(cleanup, queue); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
223 |
pending.add(cleanupWeak); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
224 |
System.out.printf(" fdWeak: %s%n msWeak: %s%n cleanupWeak: %s%n", |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
225 |
fdWeak, msWeak, cleanupWeak); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
226 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
227 |
if (altFinalizer != null) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
228 |
WeakReference<Object> altFinalizerWeak = new WeakReference<>(altFinalizer, queue); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
229 |
pending.add(altFinalizerWeak); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
230 |
System.out.printf(" fdWeak: %s%n msWeak: %s%n altFinalizerWeak: %s%n", |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
231 |
fdWeak, msWeak, altFinalizerWeak); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
232 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
233 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
234 |
AtomicInteger closeCounter = fis instanceof StreamOverrides |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
235 |
? ((StreamOverrides)fis).closeCounter() : null; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
236 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
237 |
Reference<?> r; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
238 |
while (((r = queue.remove(1000L)) != null) |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
239 |
|| !pending.isEmpty()) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
240 |
System.out.printf(" r: %s, pending: %d%n", |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
241 |
r, pending.size()); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
242 |
if (r != null) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
243 |
pending.remove(r); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
244 |
} else { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
245 |
fis = null; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
246 |
fd = null; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
247 |
cleanup = null; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
248 |
altFinalizer = null; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
249 |
System.gc(); // attempt to reclaim them |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
250 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
251 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
252 |
Reference.reachabilityFence(fd); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
253 |
Reference.reachabilityFence(fis); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
254 |
Reference.reachabilityFence(cleanup); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
255 |
Reference.reachabilityFence(altFinalizer); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
256 |
|
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
257 |
// Confirm the correct number of calls to close depending on the cleanup type |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
258 |
switch (cleanType) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
259 |
case CLEANER: |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
260 |
if (closeCounter != null && closeCounter.get() > 0) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
261 |
throw new RuntimeException("Close should not have been called: count: " |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
262 |
+ closeCounter); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
263 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
264 |
break; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
265 |
case CLOSE: |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
266 |
if (closeCounter == null || closeCounter.get() == 0) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
267 |
throw new RuntimeException("Close should have been called: count: 0"); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
268 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
269 |
break; |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
270 |
} |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
271 |
} catch (Exception ex) { |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
272 |
ex.printStackTrace(System.out); |
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
273 |
return 1; |
2 | 274 |
} |
48224
be0df5ab3093
8080225: FileInput/OutputStream/FileChannel cleanup should be improved
rriggs
parents:
47216
diff
changeset
|
275 |
return 0; |
2 | 276 |
} |
48941 | 277 |
|
278 |
/** |
|
279 |
* Method to list the open file descriptors (if supported by the 'lsof' command). |
|
280 |
*/ |
|
281 |
static void listProcFD() { |
|
282 |
List<String> lsofDirs = List.of("/usr/bin", "/usr/sbin"); |
|
283 |
Optional<Path> lsof = lsofDirs.stream() |
|
284 |
.map(s -> Paths.get(s, "lsof")) |
|
285 |
.filter(f -> Files.isExecutable(f)) |
|
286 |
.findFirst(); |
|
287 |
lsof.ifPresent(exe -> { |
|
288 |
try { |
|
289 |
System.out.printf("Open File Descriptors:%n"); |
|
290 |
long pid = ProcessHandle.current().pid(); |
|
291 |
ProcessBuilder pb = new ProcessBuilder(exe.toString(), "-p", Integer.toString((int) pid)); |
|
292 |
pb.inheritIO(); |
|
293 |
Process p = pb.start(); |
|
294 |
p.waitFor(10, TimeUnit.SECONDS); |
|
295 |
} catch (IOException | InterruptedException ie) { |
|
296 |
ie.printStackTrace(); |
|
297 |
} |
|
298 |
}); |
|
299 |
} |
|
2 | 300 |
} |