1 /* 2 * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. 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 * 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. 22 */ 23 24 /* 25 * @test 26 * @bug 8191278 27 * @requires os.family != "windows" 28 * @requires vm.flavor != "zero" 29 * @summary Check that SIGBUS errors caused by memory accesses in Unsafe_CopyMemory() 30 * and UnsafeCopySwapMemory() get converted to java.lang.InternalError exceptions. 31 * @modules java.base/jdk.internal.misc 32 * java.base/java.nio:+open 33 * 34 * @library /test/lib 35 * @build sun.hotspot.WhiteBox 36 * @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox 37 * 38 * @run main/othervm -XX:CompileCommand=exclude,*InternalErrorTest.main -XX:CompileCommand=inline,*.get -XX:CompileCommand=inline,*Unsafe.* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI InternalErrorTest 39 */ 40 41 import java.io.File; 42 import java.io.IOException; 43 import java.io.RandomAccessFile; 44 import java.lang.reflect.Field; 45 import java.lang.reflect.Method; 46 import java.nio.MappedByteBuffer; 47 import java.nio.channels.FileChannel; 48 import java.nio.file.Files; 49 import jdk.internal.misc.Unsafe; 50 import sun.hotspot.WhiteBox; 51 52 // Test that illegal memory access errors in Unsafe_CopyMemory0() and 53 // UnsafeCopySwapMemory() that cause SIGBUS errors result in 54 // java.lang.InternalError exceptions, not JVM crashes. 55 public class InternalErrorTest { 56 57 private static final Unsafe unsafe = Unsafe.getUnsafe(); 58 private static final int pageSize = WhiteBox.getWhiteBox().getVMPageSize(); 59 private static final String expectedErrorMsg = "fault occurred in a recent unsafe memory access"; 60 private static final String failureMsg1 = "InternalError not thrown"; 61 private static final String failureMsg2 = "Wrong InternalError: "; 62 main(String[] args)63 public static void main(String[] args) throws Throwable { 64 Unsafe unsafe = Unsafe.getUnsafe(); 65 66 String currentDir = System.getProperty("test.classes"); 67 File file = new File(currentDir, "tmpFile.txt"); 68 69 StringBuilder s = new StringBuilder(); 70 for (int i = 1; i < pageSize + 1000; i++) { 71 s.append("1"); 72 } 73 Files.write(file.toPath(), s.toString().getBytes()); 74 FileChannel fileChannel = new RandomAccessFile(file, "r").getChannel(); 75 MappedByteBuffer buffer = 76 fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size()); 77 78 // Get address of mapped memory. 79 long mapAddr = 0; 80 try { 81 Field af = java.nio.Buffer.class.getDeclaredField("address"); 82 af.setAccessible(true); 83 mapAddr = af.getLong(buffer); 84 } catch (Exception f) { 85 throw f; 86 } 87 long allocMem = unsafe.allocateMemory(4000); 88 89 for (int i = 0; i < 3; i++) { 90 test(buffer, unsafe, mapAddr, allocMem, i); 91 } 92 93 Files.write(file.toPath(), "2".getBytes()); 94 buffer.position(buffer.position() + pageSize); 95 for (int i = 0; i < 3; i++) { 96 try { 97 test(buffer, unsafe, mapAddr, allocMem, i); 98 WhiteBox.getWhiteBox().forceSafepoint(); 99 throw new RuntimeException(failureMsg1); 100 } catch (InternalError e) { 101 if (!e.getMessage().contains(expectedErrorMsg)) { 102 throw new RuntimeException(failureMsg2 + e.getMessage()); 103 } 104 } 105 } 106 107 Method m = InternalErrorTest.class.getMethod("test", MappedByteBuffer.class, Unsafe.class, long.class, long.class, int.class); 108 WhiteBox.getWhiteBox().enqueueMethodForCompilation(m, 3); 109 110 for (int i = 0; i < 3; i++) { 111 try { 112 test(buffer, unsafe, mapAddr, allocMem, i); 113 WhiteBox.getWhiteBox().forceSafepoint(); 114 throw new RuntimeException(failureMsg1); 115 } catch (InternalError e) { 116 if (!e.getMessage().contains(expectedErrorMsg)) { 117 throw new RuntimeException(failureMsg2 + e.getMessage()); 118 } 119 } 120 } 121 122 WhiteBox.getWhiteBox().enqueueMethodForCompilation(m, 4); 123 124 for (int i = 0; i < 3; i++) { 125 try { 126 test(buffer, unsafe, mapAddr, allocMem, i); 127 WhiteBox.getWhiteBox().forceSafepoint(); 128 throw new RuntimeException(failureMsg1); 129 } catch (InternalError e) { 130 if (!e.getMessage().contains(expectedErrorMsg)) { 131 throw new RuntimeException(failureMsg2 + e.getMessage()); 132 } 133 } 134 } 135 136 System.out.println("Success"); 137 } 138 test(MappedByteBuffer buffer, Unsafe unsafe, long mapAddr, long allocMem, int type)139 public static void test(MappedByteBuffer buffer, Unsafe unsafe, long mapAddr, long allocMem, int type) { 140 switch (type) { 141 case 0: 142 // testing Unsafe.copyMemory, trying to access a word from next page after truncation. 143 buffer.get(new byte[8]); 144 break; 145 case 1: 146 // testing Unsafe.copySwapMemory, trying to access next page after truncation. 147 unsafe.copySwapMemory(null, mapAddr + pageSize, new byte[4000], 16, 2000, 2); 148 break; 149 case 2: 150 // testing Unsafe.copySwapMemory, trying to access next page after truncation. 151 unsafe.copySwapMemory(null, mapAddr + pageSize, null, allocMem, 2000, 2); 152 break; 153 } 154 } 155 156 } 157