1 /* 2 * Copyright (c) 2002, 2016, 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 import java.nio.ByteBuffer; 25 import java.util.Properties; 26 27 public class LimitDirectMemory { 28 private static final int K = 1024; 29 30 public static void main(String [] args) throws Exception { 31 if (args.length < 2) 32 throw new RuntimeException(); 33 boolean throwp = parseThrow(args[0]); 34 int size = parseSize(args[1]); 35 int incr = (args.length > 2 ? parseSize(args[2]) : size); 36 37 Properties p = System.getProperties(); 38 if (p.getProperty("sun.nio.MaxDirectMemorySize") != null) 39 throw new RuntimeException("sun.nio.MaxDirectMemorySize defined"); 40 41 ByteBuffer [] b = new ByteBuffer[K]; 42 43 // Fill up most/all of the direct memory 44 int i = 0; 45 while (size >= incr) { 46 b[i++] = ByteBuffer.allocateDirect(incr); 47 size -= incr; 48 } 49 50 if (throwp) { 51 try { 52 b[i] = ByteBuffer.allocateDirect(incr); 53 throw new RuntimeException("OutOfMemoryError not thrown: " 54 + incr); 55 } catch (OutOfMemoryError e) { 56 e.printStackTrace(System.out); 57 System.out.println("OK - Error thrown as expected "); 58 } 59 } else { 60 b[i] = ByteBuffer.allocateDirect(incr); 61 System.out.println("OK - Error not thrown"); 62 } 63 } 64 65 private static boolean parseThrow(String s) { 66 if (s.equals("true")) return true; 67 if (s.equals("false")) return false; 68 throw new RuntimeException("Unrecognized expectation: " + s); 69 } 70 71 private static int parseSize(String size) throws Exception { 72 73 if (size.equals("DEFAULT")) 74 return (int)Runtime.getRuntime().maxMemory(); 75 if (size.equals("DEFAULT+1")) 76 return (int)Runtime.getRuntime().maxMemory() + 1; 77 if (size.equals("DEFAULT+1M")) 78 return (int)Runtime.getRuntime().maxMemory() + (1 << 20); 79 if (size.equals("DEFAULT-1")) 80 return (int)Runtime.getRuntime().maxMemory() - 1; 81 if (size.equals("DEFAULT/2")) 82 return (int)Runtime.getRuntime().maxMemory() / 2; 83 84 int idx = 0, len = size.length(); 85 86 87 for (int i = 0; i < len; i++) { 88 if (Character.isDigit(size.charAt(i))) idx++; 89 else break; 90 } 91 92 if (idx == 0) 93 throw new RuntimeException("No digits detected: " + size); 94 95 int result = Integer.parseInt(size.substring(0, idx)); 96 97 if (idx < len) { 98 for (int i = idx; i < len; i++) { 99 switch(size.charAt(i)) { 100 case 'T': case 't': result *= K; // fall through 101 case 'G': case 'g': result *= K; // fall through 102 case 'M': case 'm': result *= K; // fall through 103 case 'K': case 'k': result *= K; 104 break; 105 default: 106 throw new RuntimeException("Unrecognized size: " + size); 107 } 108 } 109 } 110 return result; 111 } 112 }