1 /* 2 * Copyright (c) 2014, 2018, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.jfr.jvm; 26 27 28 import java.io.FileReader; 29 import java.io.IOException; 30 import java.nio.file.Files; 31 import java.nio.file.Path; 32 import java.nio.file.Paths; 33 import java.util.ArrayList; 34 import java.util.concurrent.Callable; 35 36 import jdk.jfr.AnnotationElement; 37 import jdk.jfr.Configuration; 38 import jdk.jfr.Description; 39 import jdk.jfr.Event; 40 import jdk.jfr.EventFactory; 41 import jdk.jfr.EventSettings; 42 import jdk.jfr.EventType; 43 import jdk.jfr.FlightRecorder; 44 import jdk.jfr.FlightRecorderListener; 45 import jdk.jfr.FlightRecorderPermission; 46 import jdk.jfr.Label; 47 import jdk.jfr.Recording; 48 import jdk.jfr.RecordingState; 49 import jdk.jfr.SettingControl; 50 import jdk.jfr.ValueDescriptor; 51 import jdk.jfr.consumer.RecordedClass; 52 import jdk.jfr.consumer.RecordedEvent; 53 import jdk.jfr.consumer.RecordedFrame; 54 import jdk.jfr.consumer.RecordedMethod; 55 import jdk.jfr.consumer.RecordedObject; 56 import jdk.jfr.consumer.RecordedStackTrace; 57 import jdk.jfr.consumer.RecordedThread; 58 import jdk.jfr.consumer.RecordedThreadGroup; 59 import jdk.jfr.consumer.RecordingFile; 60 import jdk.management.jfr.ConfigurationInfo; 61 import jdk.management.jfr.EventTypeInfo; 62 import jdk.management.jfr.FlightRecorderMXBean; 63 import jdk.management.jfr.RecordingInfo; 64 import jdk.management.jfr.SettingDescriptorInfo; 65 66 /* 67 * @test TestUnsupportedVM 68 * @key jfr 69 * 70 * @modules jdk.jfr 71 * jdk.management.jfr 72 * 73 * @run main/othervm -Dprepare-recording=true jdk.jfr.jvm.TestUnsupportedVM 74 * @run main/othervm -Djfr.unsupported.vm=true jdk.jfr.jvm.TestUnsupportedVM 75 */ 76 public class TestUnsupportedVM { 77 78 private static Path RECORDING_FILE = Paths.get("recording.jfr"); 79 private static Class<?> [] APIClasses = { 80 AnnotationElement.class, 81 Configuration.class, 82 ConfigurationInfo.class, 83 Event.class, 84 EventFactory.class, 85 EventSettings.class, 86 EventType.class, 87 EventTypeInfo.class, 88 FlightRecorder.class, 89 FlightRecorderPermission.class, 90 FlightRecorderListener.class, 91 FlightRecorderMXBean.class, 92 RecordedClass.class, 93 RecordedEvent.class, 94 RecordedFrame.class, 95 RecordedMethod.class, 96 RecordedObject.class, 97 RecordedStackTrace.class, 98 RecordedThread.class, 99 RecordedThreadGroup.class, 100 Recording.class, 101 RecordingFile.class, 102 RecordingInfo.class, 103 RecordingState.class, 104 SettingControl.class, 105 SettingDescriptorInfo.class, 106 ValueDescriptor.class 107 }; 108 // * @run main/othervm -Dprepare-recording=true jdk.jfr.jvm.TestUnsupportedVM 109 @Label("My Event") 110 @Description("My fine event") 111 static class MyEvent extends Event { 112 int myValue; 113 } 114 115 public static void main(String... args) throws Exception { 116 if (Boolean.getBoolean("prepare-recording")) { 117 Recording r = new Recording(Configuration.getConfiguration("default")); 118 r.start(); 119 r.stop(); 120 r.dump(RECORDING_FILE); 121 r.close(); 122 return; 123 } 124 125 System.out.println("jdk.jfr.unsupportedvm=" + System.getProperty("jdk.jfr.unsupportedvm")); 126 // Class FlightRecorder 127 if (FlightRecorder.isAvailable()) { 128 throw new AssertionError("JFR should not be available on an unsupported VM"); 129 } 130 131 if (FlightRecorder.isInitialized()) { 132 throw new AssertionError("JFR should not be initialized on an unsupported VM"); 133 } 134 135 assertIllegalStateException(() -> FlightRecorder.getFlightRecorder()); 136 assertSwallow(() -> FlightRecorder.addListener(new FlightRecorderListener() {})); 137 assertSwallow(() -> FlightRecorder.removeListener(new FlightRecorderListener() {})); 138 assertSwallow(() -> FlightRecorder.register(MyEvent.class)); 139 assertSwallow(() -> FlightRecorder.unregister(MyEvent.class)); 140 assertSwallow(() -> FlightRecorder.addPeriodicEvent(MyEvent.class, new Runnable() { public void run() {} })); 141 assertSwallow(() -> FlightRecorder.removePeriodicEvent(new Runnable() { public void run() {} })); 142 143 // Class Configuration 144 if (!Configuration.getConfigurations().isEmpty()) { 145 throw new AssertionError("Configuration files should not exist on an unsupported VM"); 146 } 147 Path jfcFile = Files.createTempFile("my", ".jfr"); 148 assertIOException(() -> Configuration.getConfiguration("default")); 149 assertIOException(() -> Configuration.create(jfcFile)); 150 assertIOException(() -> Configuration.create(new FileReader(jfcFile.toFile()))); 151 152 // Class EventType 153 assertInternalError(() -> EventType.getEventType(MyEvent.class)); 154 155 // Class EventFactory 156 assertInternalError(() -> EventFactory.create(new ArrayList<>(), new ArrayList<>())); 157 158 // Create a static event 159 MyEvent myEvent = new MyEvent(); 160 myEvent.begin(); 161 myEvent.end(); 162 myEvent.shouldCommit(); 163 myEvent.commit(); 164 165 // Trigger class initialization failure 166 for (Class<?> c : APIClasses) { 167 assertNoClassInitFailure(c); 168 } 169 170 // jdk.jfr.consumer.* 171 // Only run this part of tests if we are on VM 172 // that can produce a recording file 173 if (Files.exists(RECORDING_FILE)) { 174 for(RecordedEvent re : RecordingFile.readAllEvents(RECORDING_FILE)) { 175 System.out.println(re); 176 } 177 } 178 } 179 180 private static void assertNoClassInitFailure(Class<?> clazz) { 181 try { 182 Class.forName(clazz.getName(), true, clazz.getClassLoader()); 183 } catch (ClassNotFoundException e) { 184 throw new AssertionError("Could not find public API class on unsupported VM"); 185 } 186 } 187 188 private static void assertInternalError(Runnable r) { 189 try { 190 r.run(); 191 } catch (InternalError e) { 192 // OK, as expected 193 return; 194 } 195 throw new AssertionError("Expected InternalError on an unsupported JVM"); 196 } 197 198 private static void assertIOException(Callable<?> c) { 199 try { 200 c.call(); 201 } catch (Exception e) { 202 if (e.getClass() == IOException.class) { 203 return; 204 } 205 } 206 throw new AssertionError("Expected IOException on an unsupported JVM"); 207 } 208 209 private static void assertIllegalStateException(Runnable r) throws Exception { 210 try { 211 r.run(); 212 } catch (IllegalStateException ise) { 213 if (!ise.getMessage().equals("Flight Recorder is not supported on this VM")) { 214 throw new AssertionError("Expected 'Flight Recorder is not supported on this VM'"); 215 } 216 } 217 } 218 219 private static void assertSwallow(Runnable r) throws Exception { 220 try { 221 r.run(); 222 } catch (Exception e) { 223 throw new AssertionError("Unexpected exception '" + e.getMessage() + " on an unspported VM"); 224 } 225 } 226 }