JDK9Wrappers.java revision 3653:dd56c243c199
1/* 2 * Copyright (c) 2015, 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. 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 26package com.sun.tools.javac.util; 27 28import java.lang.reflect.InvocationTargetException; 29import java.lang.reflect.Method; 30import java.nio.file.Path; 31import java.util.Collection; 32import java.util.ServiceLoader; 33 34/** 35 * This class provides wrappers for classes and methods that are new in JDK 9, and which are not 36 * available on older versions of the platform on which javac may be compiled and run. 37 * In future releases, when javac is always compiled on JDK 9 or later, the use of these wrappers 38 * can be replaced by use of the real underlying classes. 39 * 40 * <p>Wrapper classes provide a subset of the API of the wrapped classes, as needed for use 41 * in javac. Wrapper objects contain an {@code Object} reference to the underlying runtime object, 42 * and {@code Class} and {@code Method} objects for obtaining or using such instances via 43 * runtime reflection. The {@code Class} and {@code Method} objects are set up on a per-class 44 * basis, by an {@code init} method, which is called from static methods on the wrapper class, 45 * or in the constructor, when instances are created. 46 * <p> 47 * 48 * <p><b>This is NOT part of any supported API. 49 * If you write code that depends on this, you do so at your own risk. 50 * This code and its internal interfaces are subject to change or 51 * deletion without notice.</b> 52 */ 53public class JDK9Wrappers { 54 55 /** 56 * Helper class for new method in java.util.ServiceLoader. 57 */ 58 public static final class ServiceLoaderHelper { 59 @SuppressWarnings("unchecked") 60 public static <S> ServiceLoader<S> load(Layer layer, Class<S> service) { 61 try { 62 init(); 63 Object result = loadMethod.invoke(null, layer.theRealLayer, service); 64 return (ServiceLoader<S>)result; 65 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 66 | SecurityException ex) { 67 throw new Abort(ex); 68 } 69 } 70 71 // ----------------------------------------------------------------------------------------- 72 73 private static Method loadMethod = null; 74 75 private static void init() { 76 if (loadMethod == null) { 77 try { 78 Class<?> layerClass = Layer.layerClass; 79 loadMethod = ServiceLoader.class.getDeclaredMethod("load", layerClass, Class.class); 80 } catch (NoSuchMethodException | SecurityException ex) { 81 throw new Abort(ex); 82 } 83 } 84 } 85 } 86 87 /** 88 * Wrapper class for java.lang.module.ModuleFinder. 89 */ 90 public static class ModuleFinder { 91 private final Object theRealModuleFinder; 92 93 private ModuleFinder(Object moduleFinder) { 94 this.theRealModuleFinder = moduleFinder; 95 init(); 96 } 97 98 public static ModuleFinder of(Path... dirs) { 99 try { 100 init(); 101 Object result = ofMethod.invoke(null, (Object)dirs); 102 ModuleFinder mFinder = new ModuleFinder(result); 103 return mFinder; 104 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 105 | SecurityException ex) { 106 throw new Abort(ex); 107 } 108 } 109 110 // ----------------------------------------------------------------------------------------- 111 112 private static Class<?> moduleFinderClass = null; 113 private static Method ofMethod; 114 115 static final Class<?> getModuleFinderClass() { 116 init(); 117 return moduleFinderClass; 118 } 119 120 private static void init() { 121 if (moduleFinderClass == null) { 122 try { 123 moduleFinderClass = Class.forName("java.lang.module.ModuleFinder", false, null); 124 ofMethod = moduleFinderClass.getDeclaredMethod("of", Path[].class); 125 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 126 throw new Abort(ex); 127 } 128 } 129 } 130 } 131 132 /** 133 * Wrapper class for java.lang.reflect.Module. To materialize a handle use the static factory 134 * methods Module#getModule(Class<?>) or Module#getUnnamedModule(ClassLoader). 135 */ 136 public static class Module { 137 138 private final Object theRealModule; 139 140 private Module(Object module) { 141 this.theRealModule = module; 142 init(); 143 } 144 145 public static Module getModule(Class<?> clazz) { 146 try { 147 init(); 148 Object result = getModuleMethod.invoke(clazz, new Object[0]); 149 return new Module(result); 150 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 151 | SecurityException ex) { 152 throw new Abort(ex); 153 } 154 } 155 156 public static Module getUnnamedModule(ClassLoader classLoader) { 157 try { 158 init(); 159 Object result = getUnnamedModuleMethod.invoke(classLoader, new Object[0]); 160 return new Module(result); 161 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 162 | SecurityException ex) { 163 throw new Abort(ex); 164 } 165 } 166 167 public Module addExports(String pn, Module other) { 168 try { 169 addExportsMethod.invoke(theRealModule, new Object[] { pn, other.theRealModule}); 170 } catch (IllegalAccessException | InvocationTargetException ex) { 171 throw new Abort(ex); 172 } 173 return this; 174 } 175 176 public Module addUses(Class<?> st) { 177 try { 178 addUsesMethod.invoke(theRealModule, new Object[] { st }); 179 } catch (IllegalAccessException | InvocationTargetException ex) { 180 throw new Abort(ex); 181 } 182 return this; 183 } 184 185 // ----------------------------------------------------------------------------------------- 186 // on java.lang.reflect.Module 187 private static Method addExportsMethod = null; 188 // on java.lang.reflect.Module 189 private static Method addUsesMethod = null; 190 // on java.lang.Class 191 private static Method getModuleMethod; 192 // on java.lang.ClassLoader 193 private static Method getUnnamedModuleMethod; 194 195 private static void init() { 196 if (addExportsMethod == null) { 197 try { 198 Class<?> moduleClass = Class.forName("java.lang.reflect.Module", false, null); 199 addUsesMethod = moduleClass.getDeclaredMethod("addUses", new Class<?>[] { Class.class }); 200 addExportsMethod = moduleClass.getDeclaredMethod("addExports", 201 new Class<?>[] { String.class, moduleClass }); 202 getModuleMethod = Class.class.getDeclaredMethod("getModule", new Class<?>[0]); 203 getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule", new Class<?>[0]); 204 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 205 throw new Abort(ex); 206 } 207 } 208 } 209 } 210 211 /** 212 * Wrapper class for java.lang.module.Configuration. 213 */ 214 public static final class Configuration { 215 private final Object theRealConfiguration; 216 217 private Configuration(Object configuration) { 218 this.theRealConfiguration = configuration; 219 init(); 220 } 221 222 public Configuration resolveRequiresAndUses( 223 ModuleFinder beforeFinder, 224 ModuleFinder afterFinder, 225 Collection<String> roots) { 226 try { 227 Object result = resolveRequiresAndUsesMethod.invoke(theRealConfiguration, 228 beforeFinder.theRealModuleFinder, 229 afterFinder.theRealModuleFinder, 230 roots 231 ); 232 Configuration configuration = new Configuration(result); 233 return configuration; 234 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 235 | SecurityException ex) { 236 throw new Abort(ex); 237 } 238 } 239 240 // ----------------------------------------------------------------------------------------- 241 242 private static Class<?> configurationClass = null; 243 private static Method resolveRequiresAndUsesMethod; 244 245 static final Class<?> getConfigurationClass() { 246 init(); 247 return configurationClass; 248 } 249 250 private static void init() { 251 if (configurationClass == null) { 252 try { 253 configurationClass = Class.forName("java.lang.module.Configuration", false, null); 254 Class<?> moduleFinderInterface = ModuleFinder.getModuleFinderClass(); 255 resolveRequiresAndUsesMethod = configurationClass.getDeclaredMethod("resolveRequiresAndUses", 256 moduleFinderInterface, 257 moduleFinderInterface, 258 Collection.class 259 ); 260 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 261 throw new Abort(ex); 262 } 263 } 264 } 265 } 266 267 /** 268 * Wrapper class for java.lang.module.Layer. 269 */ 270 public static final class Layer { 271 private final Object theRealLayer; 272 273 private Layer(Object layer) { 274 this.theRealLayer = layer; 275 } 276 277 public static Layer boot() { 278 try { 279 init(); 280 Object result = bootMethod.invoke(null); 281 Layer layer = new Layer(result); 282 return layer; 283 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 284 | SecurityException ex) { 285 throw new Abort(ex); 286 } 287 } 288 289 public Configuration configuration() { 290 try { 291 Object result = configurationMethod.invoke(theRealLayer); 292 Configuration configuration = new Configuration(result); 293 return configuration; 294 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 295 | SecurityException ex) { 296 throw new Abort(ex); 297 } 298 } 299 300 public Layer defineModulesWithOneLoader(Configuration configuration, ClassLoader parentClassLoader) { 301 try { 302 Object result = defineModulesWithOneLoaderMethod.invoke( 303 theRealLayer, configuration.theRealConfiguration, parentClassLoader); 304 Layer layer = new Layer(result); 305 return layer; 306 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 307 | SecurityException ex) { 308 throw new Abort(ex); 309 } 310 } 311 312 // ----------------------------------------------------------------------------------------- 313 314 private static Class<?> layerClass = null; 315 private static Method bootMethod; 316 private static Method defineModulesWithOneLoaderMethod; 317 private static Method configurationMethod; 318 319 private static void init() { 320 if (layerClass == null) { 321 try { 322 layerClass = Class.forName("java.lang.reflect.Layer", false, null); 323 bootMethod = layerClass.getDeclaredMethod("boot"); 324 defineModulesWithOneLoaderMethod = layerClass.getDeclaredMethod("defineModulesWithOneLoader", 325 Configuration.getConfigurationClass(), 326 ClassLoader.class); 327 configurationMethod = layerClass.getDeclaredMethod("configuration"); 328 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 329 throw new Abort(ex); 330 } 331 } 332 } 333 } 334 335 336 /** 337 * Helper class for new method in jdk.internal.misc.VM. 338 */ 339 public static final class VMHelper { 340 public static final String VM_CLASSNAME = "jdk.internal.misc.VM"; 341 342 @SuppressWarnings("unchecked") 343 public static String[] getRuntimeArguments() { 344 try { 345 init(); 346 Object result = getRuntimeArgumentsMethod.invoke(null); 347 return (String[])result; 348 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException 349 | SecurityException ex) { 350 throw new Abort(ex); 351 } 352 } 353 354 // ----------------------------------------------------------------------------------------- 355 356 private static Class<?> vmClass = null; 357 private static Method getRuntimeArgumentsMethod = null; 358 359 private static void init() { 360 if (vmClass == null) { 361 try { 362 vmClass = Class.forName(VM_CLASSNAME, false, null); 363 getRuntimeArgumentsMethod = vmClass.getDeclaredMethod("getRuntimeArguments"); 364 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { 365 throw new Abort(ex); 366 } 367 } 368 } 369 } 370} 371