8156602: javac crashes again on Windows 32-bit with ClosedChannelException

Reviewed-by: alanb
This commit is contained in:
Jim Laskey 2016-05-20 11:41:29 -03:00
parent 65a33061ce
commit 3648a0f15f
4 changed files with 138 additions and 6 deletions

View File

@ -27,6 +27,8 @@ package jdk.internal.jimage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
@ -98,8 +100,34 @@ public class BasicImageReader implements AutoCloseable {
}
// Open the file only if no memory map yet or is 32 bit jvm
channel = map != null && MAP_ALL ? null :
FileChannel.open(imagePath, StandardOpenOption.READ);
if (map != null && MAP_ALL) {
channel = null;
} else {
channel = FileChannel.open(imagePath, StandardOpenOption.READ);
// No lambdas during bootstrap
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
if (BasicImageReader.class.getClassLoader() == null) {
try {
Class<?> fileChannelImpl =
Class.forName("sun.nio.ch.FileChannelImpl");
Method setUninterruptible =
fileChannelImpl.getMethod("setUninterruptible");
setUninterruptible.invoke(channel);
} catch (ClassNotFoundException |
NoSuchMethodException |
IllegalAccessException |
InvocationTargetException ex) {
// fall thru - will only happen on JDK-8 systems where this code
// is only used by tools using jrt-fs (non-critical.)
}
}
return null;
}
});
}
// If no memory map yet and 64 bit jvm then memory map entire file
if (MAP_ALL && map == null) {

View File

@ -40,7 +40,6 @@ import java.nio.channels.OverlappingFileLockException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectableChannel;
import java.nio.channels.WritableByteChannel;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.List;
@ -83,6 +82,9 @@ public class FileChannelImpl
// Lock for operations involving position and size
private final Object positionLock = new Object();
// Positional-read is not interruptible
private volatile boolean uninterruptible;
private FileChannelImpl(FileDescriptor fd, String path, boolean readable,
boolean writable, Object parent)
{
@ -108,6 +110,10 @@ public class FileChannelImpl
throw new ClosedChannelException();
}
public void setUninterruptible() {
uninterruptible = true;
}
// -- Standard channel operations --
protected void implCloseChannel() throws IOException {
@ -733,8 +739,10 @@ public class FileChannelImpl
assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
int n = 0;
int ti = -1;
boolean interruptible = !uninterruptible;
try {
begin();
if (interruptible) begin();
ti = threads.add();
if (!isOpen())
return -1;
@ -744,7 +752,7 @@ public class FileChannelImpl
return IOStatus.normalize(n);
} finally {
threads.remove(ti);
end(n > 0);
if (interruptible) end(n > 0);
assert IOStatus.check(n);
}
}

View File

@ -76,6 +76,7 @@ jdk_lang = \
jdk/lambda \
jdk/internal/misc \
jdk/internal/ref \
jdk/internal/jimage \
jdk/modules \
vm
@ -352,7 +353,7 @@ jdk_desktop = \
# SwingSet3 tests.
jdk_client_sanity = \
sanity/client/SwingSet
###############################################################################
#
# Serviceability sanity groups

View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2015, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.lang.reflect.Layer;
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/*
* jimage shared open testing.
* @test
* @summary Test to see if thread interrupt handling interferes with other threads.
* @build JImageOpenTest.java
* @run main/othervm -Djdk.image.map.all=false JImageOpenTest
*/
public class JImageOpenTest {
private static final int NTHREADS = 10;
public static void main(String[] args) throws Exception {
final FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
final Path root = fs.getPath("/modules");
final List<String> names = Files.walk(root)
.filter(p -> p.getNameCount() > 2)
.filter(p -> Layer.boot().findModule(p.getName(1).toString()).isPresent())
.map(p -> p.subpath(2, p.getNameCount()))
.map(p -> p.toString())
.filter(s -> s.endsWith(".class") && !s.endsWith("module-info.class"))
.collect(Collectors.toList());
Runnable r = new Runnable() {
@Override
public void run() {
names.forEach(name -> {
String cn = name.substring(0, name.length() - 6).replace('/', '.');
try {
Class.forName(cn, false, ClassLoader.getSystemClassLoader());
} catch (Exception ex) {
System.err.println(Thread.currentThread() + " " + ex.getClass());
}
});
}
};
Thread[] threads = new Thread[NTHREADS];
for (int i = 0; i < NTHREADS; i++) {
Thread thread = new Thread(r);
threads[i] = thread;
thread.start();
}
Thread.sleep(1);
for (int i = 0; i < NTHREADS; i++) {
Thread thread = threads[i];
if (thread.isAlive()) {
thread.interrupt();
break;
}
}
for (int i = 0; i < NTHREADS; i++) {
Thread thread = threads[i];
thread.join();
}
}
}