| 1 |
/* |
| 2 |
* $Id$ |
| 3 |
* |
| 4 |
* Copyright (C) 2003-2009 JNode.org |
| 5 |
* |
| 6 |
* This library is free software; you can redistribute it and/or modify it |
| 7 |
* under the terms of the GNU Lesser General Public License as published |
| 8 |
* by the Free Software Foundation; either version 2.1 of the License, or |
| 9 |
* (at your option) any later version. |
| 10 |
* |
| 11 |
* This library is distributed in the hope that it will be useful, but |
| 12 |
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
| 13 |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
| 14 |
* License for more details. |
| 15 |
* |
| 16 |
* You should have received a copy of the GNU Lesser General Public License |
| 17 |
* along with this library; If not, write to the Free Software Foundation, Inc., |
| 18 |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 19 |
*/ |
| 20 |
|
| 21 |
package org.jnode.vm; |
| 22 |
|
| 23 |
import java.io.IOException; |
| 24 |
import java.io.InputStream; |
| 25 |
import java.io.OutputStream; |
| 26 |
import java.io.PrintStream; |
| 27 |
import java.nio.ByteOrder; |
| 28 |
import java.util.Locale; |
| 29 |
import java.util.Properties; |
| 30 |
|
| 31 |
import javax.naming.NameNotFoundException; |
| 32 |
|
| 33 |
import org.apache.log4j.ConsoleAppender; |
| 34 |
import org.apache.log4j.Logger; |
| 35 |
import org.apache.log4j.PatternLayout; |
| 36 |
import org.jnode.naming.InitialNaming; |
| 37 |
import org.jnode.plugin.PluginManager; |
| 38 |
import org.jnode.security.JNodePermission; |
| 39 |
import org.jnode.system.BootLog; |
| 40 |
import org.jnode.system.MemoryResource; |
| 41 |
import org.jnode.system.ResourceManager; |
| 42 |
import org.jnode.system.ResourceNotFreeException; |
| 43 |
import org.jnode.system.ResourceOwner; |
| 44 |
import org.jnode.system.SimpleResourceOwner; |
| 45 |
import org.jnode.annotation.Internal; |
| 46 |
import org.jnode.annotation.KernelSpace; |
| 47 |
import org.jnode.annotation.MagicPermission; |
| 48 |
import org.jnode.annotation.PrivilegedActionPragma; |
| 49 |
import org.jnode.annotation.SharedStatics; |
| 50 |
import org.jnode.annotation.Uninterruptible; |
| 51 |
import org.jnode.vm.classmgr.AbstractExceptionHandler; |
| 52 |
import org.jnode.vm.classmgr.VmArray; |
| 53 |
import org.jnode.vm.classmgr.VmByteCode; |
| 54 |
import org.jnode.vm.classmgr.VmClassLoader; |
| 55 |
import org.jnode.vm.classmgr.VmCompiledCode; |
| 56 |
import org.jnode.vm.classmgr.VmCompiledExceptionHandler; |
| 57 |
import org.jnode.vm.classmgr.VmConstClass; |
| 58 |
import org.jnode.vm.classmgr.VmConstantPool; |
| 59 |
import org.jnode.vm.classmgr.VmMethod; |
| 60 |
import org.jnode.vm.classmgr.VmStaticField; |
| 61 |
import org.jnode.vm.classmgr.VmType; |
| 62 |
import org.jnode.vm.isolate.VmIsolate; |
| 63 |
import org.jnode.vm.memmgr.VmWriteBarrier; |
| 64 |
import org.jnode.vm.scheduler.VmProcessor; |
| 65 |
import org.jnode.vm.scheduler.VmThread; |
| 66 |
import org.vmmagic.unboxed.Address; |
| 67 |
import org.vmmagic.unboxed.Extent; |
| 68 |
import org.vmmagic.unboxed.ObjectReference; |
| 69 |
import org.vmmagic.unboxed.Offset; |
| 70 |
|
| 71 |
import sun.nio.ch.Interruptible; |
| 72 |
import sun.reflect.annotation.AnnotationType; |
| 73 |
|
| 74 |
/** |
| 75 |
* System support for the Virtual Machine |
| 76 |
* |
| 77 |
* @author Ewout Prangsma (epr@users.sourceforge.net) |
| 78 |
*/ |
| 79 |
@SharedStatics |
| 80 |
@MagicPermission |
| 81 |
public final class VmSystem { |
| 82 |
|
| 83 |
public static final int RC_HANDLER = 0xFFFFFFFB; |
| 84 |
|
| 85 |
public static final int RC_DEFHANDLER = 0xFFFFFFF1; |
| 86 |
|
| 87 |
private static boolean inited; |
| 88 |
|
| 89 |
private static VmSystemClassLoader systemLoader; |
| 90 |
|
| 91 |
private static String cmdLine; |
| 92 |
|
| 93 |
private static volatile long currentTimeMillis; |
| 94 |
|
| 95 |
private static long ghz = -1; |
| 96 |
|
| 97 |
private static long rtcIncrement; |
| 98 |
|
| 99 |
private static RTCService rtcService; |
| 100 |
|
| 101 |
private static SystemOutputStream bootOut; |
| 102 |
|
| 103 |
private static PrintStream bootOutStream; |
| 104 |
|
| 105 |
private static MemoryResource initJar; |
| 106 |
|
| 107 |
private static PrintStream out; |
| 108 |
|
| 109 |
private static final String LAYOUT = "%-5p [%c{1}]: %m%n"; |
| 110 |
|
| 111 |
private static boolean inShutdown = false; |
| 112 |
|
| 113 |
private static int exitCode = 0; |
| 114 |
|
| 115 |
static int debug = 0; |
| 116 |
|
| 117 |
/** |
| 118 |
* Initialize the Virtual Machine |
| 119 |
*/ |
| 120 |
public static void initialize() { |
| 121 |
if (!inited) { |
| 122 |
|
| 123 |
// Initialize resource manager |
| 124 |
final ResourceManager rm = ResourceManagerImpl.initialize(); |
| 125 |
|
| 126 |
/* Initialize the system classloader */ |
| 127 |
VmSystemClassLoader loader = (VmSystemClassLoader) (getVmClass(VmProcessor.current()).getLoader()); |
| 128 |
systemLoader = loader; |
| 129 |
loader.initialize(); |
| 130 |
|
| 131 |
VmSystem.out = getSystemOut(); |
| 132 |
|
| 133 |
// Initialize VmThread |
| 134 |
VmThread.initialize(); |
| 135 |
|
| 136 |
final Vm vm = Vm.getVm(); |
| 137 |
|
| 138 |
// Initialize the monitors for the heap manager |
| 139 |
Vm.getHeapManager().start(); |
| 140 |
|
| 141 |
Locale.setDefault(Locale.ENGLISH); |
| 142 |
|
| 143 |
// Find & start all processors |
| 144 |
vm.initializeProcessors(rm); |
| 145 |
|
| 146 |
/* We're done initializing */ |
| 147 |
inited = true; |
| 148 |
VmProcessor.current().systemReadyForThreadSwitch(); |
| 149 |
|
| 150 |
// Load the command line |
| 151 |
final Properties props = System.getProperties(); |
| 152 |
props.setProperty("jnode.cmdline", getCmdLine()); |
| 153 |
|
| 154 |
// Make sure that we have the default locale, |
| 155 |
// otherwise String.toLowerCase fails because it needs itself |
| 156 |
// via Locale.getDefault. |
| 157 |
//Locale.getDefault(); |
| 158 |
//Locale.setDefault(Locale.ENGLISH); |
| 159 |
|
| 160 |
// Calibrate the processors |
| 161 |
VmProcessor.current().calibrate(); |
| 162 |
|
| 163 |
// Setup class loading & compilation service |
| 164 |
LoadCompileService.start(); |
| 165 |
|
| 166 |
// Load the initial jarfile |
| 167 |
initJar = loadInitJar(rm); |
| 168 |
|
| 169 |
// Initialize log4j |
| 170 |
final Logger root = Logger.getRootLogger(); |
| 171 |
final ConsoleAppender infoApp = new ConsoleAppender(new PatternLayout(LAYOUT)); |
| 172 |
root.addAppender(infoApp); |
| 173 |
|
| 174 |
initOpenJDKSpecifics(); |
| 175 |
} |
| 176 |
} |
| 177 |
|
| 178 |
private static void initOpenJDKSpecifics() { |
| 179 |
//todo this will be moved to java.lang.System during openjdk integration |
| 180 |
sun.misc.SharedSecrets.setJavaLangAccess(new sun.misc.JavaLangAccess() { |
| 181 |
public sun.reflect.ConstantPool getConstantPool(Class klass) { |
| 182 |
return new VmConstantPool(VmType.fromClass(klass)); |
| 183 |
} |
| 184 |
|
| 185 |
public void setAnnotationType(Class klass, AnnotationType type) { |
| 186 |
klass.setAnnotationType(type); |
| 187 |
} |
| 188 |
|
| 189 |
public AnnotationType getAnnotationType(Class klass) { |
| 190 |
return klass.getAnnotationType(); |
| 191 |
} |
| 192 |
|
| 193 |
public <E extends Enum<E>> E[] getEnumConstantsShared(Class<E> klass) { |
| 194 |
return klass.getEnumConstantsShared(); |
| 195 |
} |
| 196 |
|
| 197 |
public void blockedOn(Thread t, Interruptible b) { |
| 198 |
//t.blockedOn(b); |
| 199 |
throw new UnsupportedOperationException(); |
| 200 |
} |
| 201 |
}); |
| 202 |
|
| 203 |
// Trigger initialization of the global environment variables. |
| 204 |
System.getenv(); |
| 205 |
} |
| 206 |
|
| 207 |
static boolean isInitialized() { |
| 208 |
return inited; |
| 209 |
} |
| 210 |
|
| 211 |
/** |
| 212 |
* Gets the system output stream. |
| 213 |
* |
| 214 |
* @return the system output stream |
| 215 |
*/ |
| 216 |
public static PrintStream getSystemOut() { |
| 217 |
SystemOutputStream sout = null; |
| 218 |
if (bootOut == null) { |
| 219 |
// initialization trick to avoid circularity and setting bootOut twice |
| 220 |
//todo review when migrating java.lang.System to OpenJDK |
| 221 |
sout = new SystemOutputStream(); |
| 222 |
} |
| 223 |
|
| 224 |
if (bootOut == null) { |
| 225 |
bootOut = sout; |
| 226 |
bootOutStream = new PrintStream(bootOut, true); |
| 227 |
VmIOContext.setGlobalOutStream(bootOutStream); |
| 228 |
VmIOContext.setGlobalErrStream(bootOutStream); |
| 229 |
setOut(bootOutStream); |
| 230 |
setErr(bootOutStream); |
| 231 |
return bootOutStream; |
| 232 |
} else if (VmIsolate.isRoot()) { |
| 233 |
return bootOutStream; |
| 234 |
} else { |
| 235 |
return VmIOContext.getGlobalOutStream(); |
| 236 |
} |
| 237 |
} |
| 238 |
|
| 239 |
/** |
| 240 |
* Load the initial jarfile. |
| 241 |
* |
| 242 |
* @param rm the resource manager |
| 243 |
* @return The initial jarfile resource, or null if no initial jarfile is |
| 244 |
* available. |
| 245 |
*/ |
| 246 |
private static MemoryResource loadInitJar(ResourceManager rm) { |
| 247 |
final Address start = Unsafe.getInitJarStart(); |
| 248 |
final Address end = Unsafe.getInitJarEnd(); |
| 249 |
final Extent size = end.toWord().sub(start.toWord()).toExtent(); |
| 250 |
if (size.toWord().isZero()) { |
| 251 |
// No initial jarfile |
| 252 |
BootLog.info("No initial jarfile found"); |
| 253 |
return null; |
| 254 |
} else { |
| 255 |
BootLog.info("Found initial jarfile of " + size.toInt() + "b"); |
| 256 |
try { |
| 257 |
final ResourceOwner owner = new SimpleResourceOwner("System"); |
| 258 |
return rm.claimMemoryResource(owner, start, size, |
| 259 |
ResourceManager.MEMMODE_NORMAL); |
| 260 |
} catch (ResourceNotFreeException ex) { |
| 261 |
BootLog.error("Cannot claim initjar resource", ex); |
| 262 |
return null; |
| 263 |
} |
| 264 |
} |
| 265 |
} |
| 266 |
|
| 267 |
// ------------------------------------------ |
| 268 |
// Information |
| 269 |
// ------------------------------------------ |
| 270 |
|
| 271 |
/** |
| 272 |
* This method adds some default system properties |
| 273 |
* |
| 274 |
* @param res the system properties object |
| 275 |
*/ |
| 276 |
public static void insertSystemProperties(Properties res) { |
| 277 |
|
| 278 |
final Vm vm = Vm.getVm(); |
| 279 |
final VmArchitecture arch = Vm.getArch(); |
| 280 |
|
| 281 |
// Standard Java properties |
| 282 |
res.put("file.separator", "/"); |
| 283 |
// res.put("file.encoding", "ISO-8859-1"); |
| 284 |
res.put("java.awt.graphicsenv", "org.jnode.awt.JNodeGraphicsEnvironment"); |
| 285 |
//todo |
| 286 |
// res.put("java.awt.printerjob", ""); |
| 287 |
//todo |
| 288 |
res.put("java.class.path", ":"); |
| 289 |
res.put("java.class.version", "50.0"); |
| 290 |
res.put("java.compiler", "Internal"); //todo is this needed? |
| 291 |
res.put("java.endorsed.dirs", "/jifs/lib/"); |
| 292 |
res.put("java.ext.dirs", "/jifs/lib/"); |
| 293 |
res.put("java.home", "/jnode"); |
| 294 |
res.put("java.io.tmpdir", "/jnode/tmp"); |
| 295 |
res.put("java.library.path", "/jnode/tmp"); //dummy value but needed by Runtime.loadLibrary |
| 296 |
res.put("java.runtime.name", "JNode"); |
| 297 |
res.put("java.runtime.version", vm.getVersion()); |
| 298 |
res.put("java.specification.name", "Java Platform API Specification"); |
| 299 |
res.put("java.specification.vendor", "Sun Microsystems Inc."); |
| 300 |
res.put("java.specification.version", "1.6"); |
| 301 |
res.put("java.vendor", "JNode.org"); |
| 302 |
res.put("java.vendor.url", "http://jnode.org"); |
| 303 |
res.put("java.vendor.url.bug", "http://jnode.org"); |
| 304 |
res.put("java.version", "1.6"); |
| 305 |
res.put("java.vm.info", "JNode"); |
| 306 |
res.put("java.vm.name", "JNode"); |
| 307 |
res.put("java.vm.specification.name", "Java Virtual Machine Specification"); |
| 308 |
res.put("java.vm.specification.vendor", "Sun Microsystems Inc."); |
| 309 |
res.put("java.vm.specification.version", "1.0"); |
| 310 |
res.put("java.vm.vendor", "JNode.org"); |
| 311 |
res.put("java.vm.version", vm.getVersion()); |
| 312 |
res.put("line.separator", "\n"); |
| 313 |
res.put("os.arch", arch.getName()); |
| 314 |
res.put("os.name", "JNode"); |
| 315 |
res.put("os.version", vm.getVersion()); |
| 316 |
res.put("path.separator", ":"); |
| 317 |
//todo |
| 318 |
// res.put("user.country", ""); |
| 319 |
res.put("user.dir", "/"); |
| 320 |
res.put("user.home", "/jnode/home"); |
| 321 |
res.put("user.language", "en"); |
| 322 |
res.put("user.name", "admin"); |
| 323 |
//todo |
| 324 |
// res.put("user.timezone", ""); |
| 325 |
|
| 326 |
// GNU properties |
| 327 |
res.put("gnu.cpu.endian", (arch.getByteOrder() == ByteOrder.BIG_ENDIAN) ? "big" : "little"); |
| 328 |
res.put("gnu.classpath.home.url", "system://"); |
| 329 |
res.put("gnu.classpath.vm.shortname", "jnode"); |
| 330 |
res.put("gnu.javax.swing.noGraphics2D", "true"); |
| 331 |
|
| 332 |
//----------JNode related |
| 333 |
// Log4j properties |
| 334 |
res.put("log4j.defaultInitOverride", "true"); |
| 335 |
|
| 336 |
// keep this property until transparency support works fine with all drivers |
| 337 |
res.put("org.jnode.awt.transparency", "true"); |
| 338 |
|
| 339 |
//internal classpath for javac |
| 340 |
res.put("sun.boot.class.path", ":"); |
| 341 |
|
| 342 |
res.put("swing.handleTopLevelPaint", "false"); |
| 343 |
res.put("java.protocol.handler.pkgs", "org.jnode.protocol|gnu.java.net.protocol|gnu.inet"); |
| 344 |
res.put("java.content.handler.pkgs", "gnu.java.net.content"); |
| 345 |
|
| 346 |
VmSystemSettings.insertSystemProperties(res); |
| 347 |
} |
| 348 |
|
| 349 |
/** |
| 350 |
* Returns the commandline appended to the kernel by the bootloader (e.g. grub) |
| 351 |
* |
| 352 |
* @return the commandline appended to the kernel |
| 353 |
*/ |
| 354 |
public static String getCmdLine() { |
| 355 |
if (cmdLine == null) { |
| 356 |
/* Load the command line */ |
| 357 |
final int cmdLineSize = Unsafe.getCmdLine(null); |
| 358 |
final byte[] cmdLineArr = new byte[cmdLineSize]; |
| 359 |
Unsafe.getCmdLine(cmdLineArr); |
| 360 |
cmdLine = new String(cmdLineArr).trim(); |
| 361 |
} |
| 362 |
return cmdLine; |
| 363 |
} |
| 364 |
|
| 365 |
/** |
| 366 |
* Gets the log of the bootstrap phase. |
| 367 |
* |
| 368 |
* @return String |
| 369 |
*/ |
| 370 |
public static String getBootLog() { |
| 371 |
if (bootOut != null) { |
| 372 |
return bootOut.getData(); |
| 373 |
} else { |
| 374 |
return ""; |
| 375 |
} |
| 376 |
} |
| 377 |
|
| 378 |
// ------------------------------------------ |
| 379 |
// java.lang.Object support |
| 380 |
// ------------------------------------------ |
| 381 |
|
| 382 |
/** |
| 383 |
* Gets the class of the given object |
| 384 |
* |
| 385 |
* @param obj |
| 386 |
* @return The class |
| 387 |
*/ |
| 388 |
public static Class<?> getClass(Object obj) { |
| 389 |
return getVmClass(obj).asClass(); |
| 390 |
} |
| 391 |
|
| 392 |
/** |
| 393 |
* Gets the VmClass of the given object. |
| 394 |
* |
| 395 |
* @param obj |
| 396 |
* @return VmClass |
| 397 |
*/ |
| 398 |
public static VmType<?> getVmClass(Object obj) { |
| 399 |
if (obj == null) { |
| 400 |
throw new NullPointerException(); |
| 401 |
} else { |
| 402 |
return VmMagic.getObjectType(obj); |
| 403 |
} |
| 404 |
} |
| 405 |
|
| 406 |
/** |
| 407 |
* Clone the given object |
| 408 |
* |
| 409 |
* @param obj |
| 410 |
* @return Object |
| 411 |
*/ |
| 412 |
public static Object clone(Cloneable obj) { |
| 413 |
return Vm.getHeapManager().clone(obj); |
| 414 |
} |
| 415 |
|
| 416 |
/** |
| 417 |
* Gets the hashcode of the given object |
| 418 |
* |
| 419 |
* @param obj |
| 420 |
* @return int |
| 421 |
*/ |
| 422 |
public static int getHashCode(Object obj) { |
| 423 |
if (obj == null) { |
| 424 |
// According to spec, null has zero as hashcode. |
| 425 |
return 0; |
| 426 |
} else { |
| 427 |
return ObjectReference.fromObject(obj).toAddress().toInt(); |
| 428 |
} |
| 429 |
} |
| 430 |
|
| 431 |
// ------------------------------------------ |
| 432 |
// java.lang.Class support |
| 433 |
// ------------------------------------------ |
| 434 |
|
| 435 |
public static Class forName(String className) throws ClassNotFoundException { |
| 436 |
return getContextClassLoader().asClassLoader().loadClass(className); |
| 437 |
} |
| 438 |
|
| 439 |
/** |
| 440 |
* Gets the first non-system classloader out of the current stacktrace, or |
| 441 |
* the system classloader if no other classloader is found in the current |
| 442 |
* stacktrace. |
| 443 |
* |
| 444 |
* @return The classloader |
| 445 |
*/ |
| 446 |
protected static VmClassLoader getContextClassLoader() { |
| 447 |
final VmStackReader reader = VmProcessor.current().getArchitecture() |
| 448 |
.getStackReader(); |
| 449 |
final VmSystemClassLoader systemLoader = VmSystem.systemLoader; |
| 450 |
Address f = VmMagic.getCurrentFrame(); |
| 451 |
while (reader.isValid(f)) { |
| 452 |
final VmMethod method = reader.getMethod(f); |
| 453 |
final VmClassLoader loader = method.getDeclaringClass().getLoader(); |
| 454 |
if ((loader != null) && (loader != systemLoader)) { |
| 455 |
return loader; |
| 456 |
} else { |
| 457 |
f = reader.getPrevious(f); |
| 458 |
} |
| 459 |
} |
| 460 |
return systemLoader; |
| 461 |
} |
| 462 |
|
| 463 |
// ------------------------------------------ |
| 464 |
// java.lang.SecurityManager support |
| 465 |
// ------------------------------------------ |
| 466 |
|
| 467 |
/** |
| 468 |
* Gets the current stacktrace as array of classes. |
| 469 |
* |
| 470 |
* @return Class[] |
| 471 |
*/ |
| 472 |
public static Class[] getClassContext() { |
| 473 |
final VmStackReader reader = VmProcessor.current().getArchitecture() |
| 474 |
.getStackReader(); |
| 475 |
final VmStackFrame[] stack = reader.getVmStackTrace(VmMagic |
| 476 |
.getCurrentFrame(), null, VmThread.STACKTRACE_LIMIT); |
| 477 |
final int count = stack.length; |
| 478 |
final Class[] result = new Class[count]; |
| 479 |
|
| 480 |
for (int i = 0; i < count; i++) { |
| 481 |
result[i] = stack[i].getMethod().getDeclaringClass().asClass(); |
| 482 |
} |
| 483 |
|
| 484 |
return result; |
| 485 |
} |
| 486 |
|
| 487 |
/** |
| 488 |
* Gets the current stacktrace as array of classes excluding the calls to |
| 489 |
* java.lang.reflect.Method.invoke() and org.jnode.vm.VmReflection.invoke(). |
| 490 |
* |
| 491 |
* @return Class[] |
| 492 |
*/ |
| 493 |
public static Class[] getRealClassContext() { |
| 494 |
final VmStackReader reader = VmProcessor.current().getArchitecture() |
| 495 |
.getStackReader(); |
| 496 |
final VmStackFrame[] stack = reader.getVmStackTrace(VmMagic |
| 497 |
.getCurrentFrame(), null, VmThread.STACKTRACE_LIMIT); |
| 498 |
final int count = stack.length; |
| 499 |
final Class[] result = new Class[count]; |
| 500 |
int real_count = 0; |
| 501 |
for (int i = 0; i < count; i++) { |
| 502 |
VmMethod method = stack[i].getMethod(); |
| 503 |
VmType<?> clazz = method.getDeclaringClass(); |
| 504 |
if ((method.getName().equals("invoke") && ( |
| 505 |
clazz.getName().equals("java.lang.reflect.Method") || |
| 506 |
clazz.getName().equals("org.jnode.vm.VmReflection")))) |
| 507 |
continue; |
| 508 |
|
| 509 |
result[real_count++] = clazz.asClass(); |
| 510 |
} |
| 511 |
|
| 512 |
Class[] real_result = new Class[real_count]; |
| 513 |
System.arraycopy(result, 0, real_result, 0, real_count); |
| 514 |
|
| 515 |
return real_result; |
| 516 |
} |
| 517 |
|
| 518 |
/** |
| 519 |
* Do nothing, until interrupted by an interrupts. |
| 520 |
*/ |
| 521 |
public static void idle() { |
| 522 |
Unsafe.idle(); |
| 523 |
} |
| 524 |
|
| 525 |
@Internal |
| 526 |
public static final Object allocStack(int size) { |
| 527 |
try { |
| 528 |
return Vm.getHeapManager() |
| 529 |
.newInstance( |
| 530 |
systemLoader.loadClass( |
| 531 |
"org.jnode.vm.VmSystemObject", true), size); |
| 532 |
} catch (ClassNotFoundException ex) { |
| 533 |
throw (NoClassDefFoundError) new NoClassDefFoundError() |
| 534 |
.initCause(ex); |
| 535 |
} |
| 536 |
} |
| 537 |
|
| 538 |
/** |
| 539 |
* Find an exception handler to handle the given exception in the given |
| 540 |
* frame at the given address. |
| 541 |
* |
| 542 |
* @param ex |
| 543 |
* @param frame |
| 544 |
* @param address |
| 545 |
* @return Object |
| 546 |
*/ |
| 547 |
@PrivilegedActionPragma |
| 548 |
public static Address findThrowableHandler(Throwable ex, Address frame, |
| 549 |
Address address) { |
| 550 |
|
| 551 |
try { |
| 552 |
debug++; |
| 553 |
|
| 554 |
if (ex == null) { |
| 555 |
Unsafe.debug("NPE"); |
| 556 |
throw new NullPointerException(); |
| 557 |
} |
| 558 |
if (frame == null) { |
| 559 |
Unsafe.debug("frame==null"); |
| 560 |
return null; |
| 561 |
} |
| 562 |
final VmProcessor proc = VmProcessor.current(); |
| 563 |
final VmStackReader reader = proc.getArchitecture() |
| 564 |
.getStackReader(); |
| 565 |
|
| 566 |
final VmType exClass = VmMagic.getObjectType(ex); |
| 567 |
final VmMethod method = reader.getMethod(frame); |
| 568 |
if (method == null) { |
| 569 |
Unsafe.debug("Unknown method"); |
| 570 |
return null; |
| 571 |
} |
| 572 |
|
| 573 |
// if (interpreted) { |
| 574 |
/* |
| 575 |
* Screen.debug("{ex at pc:"); Screen.debug(pc); Screen.debug(" of " + |
| 576 |
* method.getBytecodeSize()); Screen.debug(method.getName()); |
| 577 |
*/ |
| 578 |
// } |
| 579 |
final int count; |
| 580 |
final VmByteCode bc = method.getBytecode(); |
| 581 |
final VmCompiledCode cc = reader.getCompiledCode(frame); |
| 582 |
if (bc != null) { |
| 583 |
count = bc.getNoExceptionHandlers(); |
| 584 |
} else { |
| 585 |
count = 0; |
| 586 |
} |
| 587 |
// Screen.debug("eCount=" + count); |
| 588 |
for (int i = 0; i < count; i++) { |
| 589 |
final AbstractExceptionHandler eh; |
| 590 |
final VmCompiledExceptionHandler ceh; |
| 591 |
ceh = cc.getExceptionHandler(i); |
| 592 |
eh = ceh; |
| 593 |
boolean match; |
| 594 |
|
| 595 |
match = ceh.isInScope(address); |
| 596 |
|
| 597 |
if (match) { |
| 598 |
final VmConstClass catchType = eh.getCatchType(); |
| 599 |
|
| 600 |
if (catchType == null) { |
| 601 |
/* Catch all exceptions */ |
| 602 |
return Address.fromAddress(ceh.getHandler()); |
| 603 |
} else { |
| 604 |
if (!catchType.isResolved()) { |
| 605 |
SoftByteCodes.resolveClass(catchType); |
| 606 |
} |
| 607 |
final VmType handlerClass = catchType |
| 608 |
.getResolvedVmClass(); |
| 609 |
if (handlerClass != null) { |
| 610 |
if (handlerClass.isAssignableFrom(exClass)) { |
| 611 |
return Address.fromAddress(ceh.getHandler()); |
| 612 |
} |
| 613 |
} else { |
| 614 |
System.err |
| 615 |
.println("Warning: handler class==null in " |
| 616 |
+ method.getName()); |
| 617 |
} |
| 618 |
} |
| 619 |
} |
| 620 |
} |
| 621 |
|
| 622 |
if (cc.contains(address)) { |
| 623 |
return Address.fromAddress(cc.getDefaultExceptionHandler()); |
| 624 |
} else { |
| 625 |
return null; |
| 626 |
} |
| 627 |
} catch (Throwable ex2) { |
| 628 |
Unsafe.debug("Exception in findThrowableHandler"); |
| 629 |
try { |
| 630 |
ex2.printStackTrace(); |
| 631 |
} finally { |
| 632 |
Unsafe.die("findThrowableHandler"); |
| 633 |
} |
| 634 |
return null; |
| 635 |
} finally { |
| 636 |
debug--; |
| 637 |
} |
| 638 |
} |
| 639 |
|
| 640 |
// ------------------------------------------ |
| 641 |
// java.lang.System support |
| 642 |
// ------------------------------------------ |
| 643 |
|
| 644 |
/** |
| 645 |
* Copy one array to another. This is the implementation for System.arraycopy in JNode |
| 646 |
* |
| 647 |
* @param src |
| 648 |
* @param srcPos |
| 649 |
* @param dst |
| 650 |
* @param dstPos |
| 651 |
* @param length |
| 652 |
*/ |
| 653 |
@PrivilegedActionPragma |
| 654 |
public static void arrayCopy(final Object src, final int srcPos, |
| 655 |
final Object dst, final int dstPos, final int length) { |
| 656 |
Class<?> src_class = src.getClass(); |
| 657 |
Class<?> dst_class = dst.getClass(); |
| 658 |
|
| 659 |
if (!src_class.isArray()) { |
| 660 |
// Unsafe.debug('!'); |
| 661 |
throw new ArrayStoreException("src is not an array"); |
| 662 |
} |
| 663 |
|
| 664 |
if (!dst_class.isArray()) { |
| 665 |
// Unsafe.debug("dst is not an array:"); |
| 666 |
// Unsafe.debug(dst_class.getName()); |
| 667 |
throw new ArrayStoreException("dst is not an array"); |
| 668 |
} |
| 669 |
|
| 670 |
String src_name = src_class.getName(); |
| 671 |
String dst_name = dst_class.getName(); |
| 672 |
|
| 673 |
char src_type = src_name.charAt(1); |
| 674 |
char dst_type = dst_name.charAt(1); |
| 675 |
|
| 676 |
if (src_type == '[') { |
| 677 |
src_type = 'L'; |
| 678 |
} |
| 679 |
if (dst_type == '[') { |
| 680 |
dst_type = 'L'; |
| 681 |
} |
| 682 |
|
| 683 |
if (src_type != dst_type) { |
| 684 |
// Unsafe.debug("invalid array types:"); |
| 685 |
// Unsafe.debug(src_class.getName()); |
| 686 |
// Unsafe.debug(dst_class.getName()); |
| 687 |
throw new ArrayStoreException( |
| 688 |
"Incompatible array types: " + src_class.getName() + ", " + dst_class.getName()); |
| 689 |
} |
| 690 |
|
| 691 |
if (srcPos < 0) { |
| 692 |
throw new IndexOutOfBoundsException("srcPos < 0"); |
| 693 |
} |
| 694 |
if (dstPos < 0) { |
| 695 |
throw new IndexOutOfBoundsException("dstPos < 0"); |
| 696 |
} |
| 697 |
if (length < 0) { |
| 698 |
throw new IndexOutOfBoundsException("length < 0"); |
| 699 |
} |
| 700 |
|
| 701 |
final int slotSize = VmProcessor.current().getArchitecture() |
| 702 |
.getReferenceSize(); |
| 703 |
final Offset lengthOffset = Offset |
| 704 |
.fromIntSignExtend(VmArray.LENGTH_OFFSET * slotSize); |
| 705 |
final int dataOffset = VmArray.DATA_OFFSET * slotSize; |
| 706 |
|
| 707 |
final Address srcAddr = ObjectReference.fromObject(src).toAddress(); |
| 708 |
final Address dstAddr = ObjectReference.fromObject(dst).toAddress(); |
| 709 |
|
| 710 |
final int srcLen = srcAddr.loadInt(lengthOffset); |
| 711 |
final int dstLen = dstAddr.loadInt(lengthOffset); |
| 712 |
|
| 713 |
// Calc end index (if overflow, then will be < 0 ) |
| 714 |
final int srcEnd = srcPos + length; |
| 715 |
final int dstEnd = dstPos + length; |
| 716 |
|
| 717 |
if ((srcEnd > srcLen) || (srcEnd < 0)) { |
| 718 |
throw new IndexOutOfBoundsException("srcPos+length > src.length (" |
| 719 |
+ srcPos + "+" + length + " > " + srcLen + ")"); |
| 720 |
} |
| 721 |
if ((dstEnd > dstLen) || (dstEnd < 0)) { |
| 722 |
throw new IndexOutOfBoundsException("dstPos+length > dst.length"); |
| 723 |
} |
| 724 |
|
| 725 |
final int elemsize; |
| 726 |
final boolean isObjectArray; |
| 727 |
switch (src_type) { |
| 728 |
case 'Z': |
| 729 |
// Boolean |
| 730 |
case 'B': |
| 731 |
// Byte |
| 732 |
elemsize = 1; |
| 733 |
isObjectArray = false; |
| 734 |
break; |
| 735 |
case 'C': |
| 736 |
// Character |
| 737 |
case 'S': |
| 738 |
// Short |
| 739 |
elemsize = 2; |
| 740 |
isObjectArray = false; |
| 741 |
break; |
| 742 |
case 'I': |
| 743 |
// Integer |
| 744 |
case 'F': |
| 745 |
// Float |
| 746 |
elemsize = 4; |
| 747 |
isObjectArray = false; |
| 748 |
break; |
| 749 |
case 'L': |
| 750 |
// Object |
| 751 |
elemsize = slotSize; |
| 752 |
isObjectArray = true; |
| 753 |
break; |
| 754 |
case 'J': |
| 755 |
// Long |
| 756 |
case 'D': |
| 757 |
// Double |
| 758 |
elemsize = 8; |
| 759 |
isObjectArray = false; |
| 760 |
break; |
| 761 |
default: |
| 762 |
// Unsafe.debug("uat:"); |
| 763 |
// Unsafe.debug(src_type); |
| 764 |
// Unsafe.debug(src_name); |
| 765 |
throw new ArrayStoreException("Unknown array type"); |
| 766 |
} |
| 767 |
|
| 768 |
final Address srcPtr = srcAddr.add(dataOffset + (srcPos * elemsize)); |
| 769 |
final Address dstPtr = dstAddr.add(dataOffset + (dstPos * elemsize)); |
| 770 |
final Extent size = Extent.fromIntZeroExtend(length * elemsize); |
| 771 |
|
| 772 |
|
| 773 |
if (isObjectArray) { |
| 774 |
Class dst_comp_class = dst_class.getComponentType(); |
| 775 |
Class src_comp_class = src_class.getComponentType(); |
| 776 |
if (!dst_comp_class.isAssignableFrom(src_comp_class)) { |
| 777 |
//todo optimize for speed |
| 778 |
Object[] srca = (Object[]) src; |
| 779 |
Object[] dsta = (Object[]) dst; |
| 780 |
for (int i = 0; i < length; i++) { |
| 781 |
Object o = srca[srcPos + i]; |
| 782 |
if (o == null || dst_comp_class.isInstance(o)) { |
| 783 |
dsta[dstPos + i] = o; |
| 784 |
} else { |
| 785 |
throw new ArrayStoreException(); |
| 786 |
} |
| 787 |
} |
| 788 |
} else { |
| 789 |
Unsafe.copy(srcPtr, dstPtr, size); |
| 790 |
} |
| 791 |
} else { |
| 792 |
Unsafe.copy(srcPtr, dstPtr, size); |
| 793 |
} |
| 794 |
|
| 795 |
if (isObjectArray) { |
| 796 |
final VmWriteBarrier wb = Vm.getHeapManager().getWriteBarrier(); |
| 797 |
if (wb != null) { |
| 798 |
wb.arrayCopyWriteBarrier(src, srcPos, srcPos + length); |
| 799 |
} |
| 800 |
} |
| 801 |
} |
| 802 |
|
| 803 |
/** |
| 804 |
* Returns the current time in milliseconds. Note that while the unit of |
| 805 |
* time of the return value is a millisecond, the granularity of the value |
| 806 |
* depends on the underlying operating system and may be larger. For |
| 807 |
* example, many operating systems measure time in units of tens of |
| 808 |
* milliseconds. See the description of the class Date for a discussion of |
| 809 |
* slight discrepancies that may arise between "computer time" and |
| 810 |
* coordinated universal time (UTC). |
| 811 |
* <p/> |
| 812 |
* This method does call other methods and CANNOT be used in the low-level |
| 813 |
* system environment, where synchronization cannot be used. * |
| 814 |
* |
| 815 |
* @return the difference, measured in milliseconds, between the current |
| 816 |
* time and midnight, January 1, 1970 UTC |
| 817 |
*/ |
| 818 |
public static long currentTimeMillis() { |
| 819 |
|
| 820 |
if (rtcIncrement == 0) { |
| 821 |
try { |
| 822 |
final RTCService rtcService = VmSystem.rtcService; |
| 823 |
if (rtcService != null) { |
| 824 |
final long rtcTime = rtcService.getTime(); |
| 825 |
if (rtcTime == 0L) { |
| 826 |
// We don't have an RTC service yet, return an invalid, |
| 827 |
// but for now good enough value |
| 828 |
return currentTimeMillis; |
| 829 |
} else { |
| 830 |
rtcIncrement = rtcTime - currentTimeMillis; |
| 831 |
} |
| 832 |
} |
| 833 |
} catch (Exception ex) { |
| 834 |
BootLog.error("Error getting rtcIncrement ", ex); |
| 835 |
rtcIncrement = 1; |
| 836 |
} |
| 837 |
} |
| 838 |
return currentTimeMillis + rtcIncrement; |
| 839 |
} |
| 840 |
|
| 841 |
/** |
| 842 |
* <p> |
| 843 |
* Returns the current value of a nanosecond-precise system timer. |
| 844 |
* The value of the timer is an offset relative to some arbitrary fixed |
| 845 |
* time, which may be in the future (making the value negative). This |
| 846 |
* method is useful for timing events where nanosecond precision is |
| 847 |
* required. This is achieved by calling this method before and after the |
| 848 |
* event, and taking the difference between the two times: |
| 849 |
* </p> |
| 850 |
* <p> |
| 851 |
* <code>long startTime = System.nanoTime();</code><br /> |
| 852 |
* <code>... <emph>event code</emph> ...</code><br /> |
| 853 |
* <code>long endTime = System.nanoTime();</code><br /> |
| 854 |
* <code>long duration = endTime - startTime;</code><br /> |
| 855 |
* </p> |
| 856 |
* <p> |
| 857 |
* Note that the value is only nanosecond-precise, and not accurate; there |
| 858 |
* is no guarantee that the difference between two values is really a |
| 859 |
* nanosecond. Also, the value is prone to overflow if the offset |
| 860 |
* exceeds 2^63. |
| 861 |
* </p> |
| 862 |
* |
| 863 |
* @return the time of a system timer in nanoseconds. |
| 864 |
* @since 1.5 |
| 865 |
*/ |
| 866 |
public static long nanoTime() { |
| 867 |
if (ghz == -1) { |
| 868 |
final long measureDuration = 1000; // in milliseconds |
| 869 |
|
| 870 |
long start = Unsafe.getCpuCycles(); |
| 871 |
long ms_start = currentTimeMillis(); |
| 872 |
long ms_end; |
| 873 |
try { |
| 874 |
Thread.sleep(measureDuration); |
| 875 |
} catch (InterruptedException e) { |
| 876 |
//ignore |
| 877 |
} finally { |
| 878 |
ms_end = currentTimeMillis(); |
| 879 |
} |
| 880 |
long end = Unsafe.getCpuCycles(); |
| 881 |
long ms = ms_end - ms_start; |
| 882 |
if (ms <= 0) { |
| 883 |
ms = measureDuration; |
| 884 |
} |
| 885 |
|
| 886 |
ghz = (end - start) / (ms * 1000000L); |
| 887 |
if (ghz <= 0) { |
| 888 |
ghz = 0; |
| 889 |
} |
| 890 |
} |
| 891 |
|
| 892 |
if (ghz == 0) { |
| 893 |
//todo these are CPUs under 1GHz, improve this case |
| 894 |
return currentTimeMillis() * 1000000L; |
| 895 |
} |
| 896 |
|
| 897 |
return Unsafe.getCpuCycles() / ghz; |
| 898 |
} |
| 899 |
|
| 900 |
/** |
| 901 |
* Returns the number of milliseconds since booting the kernel of JNode. |
| 902 |
* <p/> |
| 903 |
* This method does not call any other method and CAN be used in the |
| 904 |
* low-level system environment, where synchronization cannot be used. |
| 905 |
* |
| 906 |
* @return The current time of the kernel |
| 907 |
* @throws org.vmmagic.pragma.UninterruptiblePragma |
| 908 |
* |
| 909 |
*/ |
| 910 |
@KernelSpace |
| 911 |
@Uninterruptible |
| 912 |
public static long currentKernelMillis() { |
| 913 |
return currentTimeMillis; |
| 914 |
} |
| 915 |
|
| 916 |
/** |
| 917 |
* @return VmClassLoader |
| 918 |
*/ |
| 919 |
public static VmSystemClassLoader getSystemClassLoader() { |
| 920 |
return systemLoader; |
| 921 |
} |
| 922 |
|
| 923 |
/** |
| 924 |
* Returns the free memory in system ram |
| 925 |
* |
| 926 |
* @return free memory in system ram |
| 927 |
*/ |
| 928 |
public static long freeMemory() { |
| 929 |
return Vm.getHeapManager().getFreeMemory(); |
| 930 |
} |
| 931 |
|
| 932 |
/** |
| 933 |
* Returns the total amount of system memory |
| 934 |
* |
| 935 |
* @return the total amount of system memory |
| 936 |
*/ |
| 937 |
public static long totalMemory() { |
| 938 |
return Vm.getHeapManager().getTotalMemory(); |
| 939 |
} |
| 940 |
|
| 941 |
/** |
| 942 |
* Call the garbage collector |
| 943 |
*/ |
| 944 |
public static void gc() { |
| 945 |
Vm.getHeapManager().gc(); |
| 946 |
} |
| 947 |
|
| 948 |
static class SystemOutputStream extends OutputStream { |
| 949 |
|
| 950 |
private StringBuffer data; |
| 951 |
|
| 952 |
/** |
| 953 |
* @see java.io.OutputStream#write(int) |
| 954 |
*/ |
| 955 |
public void write(int b) throws IOException { |
| 956 |
final char ch = (char) (b & 0xFF); |
| 957 |
Unsafe.debug(ch); |
| 958 |
if (data == null) { |
| 959 |
synchronized (this) { |
| 960 |
data = new StringBuffer(); |
| 961 |
} |
| 962 |
} |
| 963 |
data.append(ch); |
| 964 |
} |
| 965 |
|
| 966 |
/** |
| 967 |
* Returns the data written to the system output stream |
| 968 |
* |
| 969 |
* @return data written to the system output stream |
| 970 |
*/ |
| 971 |
public String getData() { |
| 972 |
return (data == null) ? "" : data.toString(); |
| 973 |
} |
| 974 |
} |
| 975 |
|
| 976 |
/** |
| 977 |
* @param rtcService The rtcService to set. |
| 978 |
*/ |
| 979 |
public static final void setRtcService(RTCService rtcService) { |
| 980 |
if (VmSystem.rtcService == null) { |
| 981 |
VmSystem.rtcService = rtcService; |
| 982 |
} |
| 983 |
} |
| 984 |
|
| 985 |
/** |
| 986 |
* @param rtcService The rtcService previously set. |
| 987 |
*/ |
| 988 |
public static final void resetRtcService(RTCService rtcService) { |
| 989 |
if (VmSystem.rtcService == rtcService) { |
| 990 |
VmSystem.rtcService = null; |
| 991 |
} |
| 992 |
} |
| 993 |
|
| 994 |
/** |
| 995 |
* @return Returns the initJar. |
| 996 |
*/ |
| 997 |
public static final MemoryResource getInitJar() { |
| 998 |
return initJar; |
| 999 |
} |
| 1000 |
|
| 1001 |
/** |
| 1002 |
* @return Returns the out. |
| 1003 |
*/ |
| 1004 |
public static final PrintStream getOut() { |
| 1005 |
return out; |
| 1006 |
} |
| 1007 |
|
| 1008 |
/** |
| 1009 |
* Calculate the speed of the current processor. |
| 1010 |
* |
| 1011 |
* @return the speed of the current processor in "JNodeMips" |
| 1012 |
*/ |
| 1013 |
@Uninterruptible |
| 1014 |
public static float calculateJNodeMips() { |
| 1015 |
final long millis = currentTimeMillis % 1000; |
| 1016 |
while (millis == (currentTimeMillis % 1000)) { |
| 1017 |
// Wait |
| 1018 |
} |
| 1019 |
long count = 0; |
| 1020 |
float dummy = 0.0f; |
| 1021 |
while (millis != (currentTimeMillis % 1000)) { |
| 1022 |
count++; |
| 1023 |
dummy += 0.5f; |
| 1024 |
} |
| 1025 |
return count / 100000.0f; |
| 1026 |
} |
| 1027 |
|
| 1028 |
/** |
| 1029 |
* Is the system shutting down. |
| 1030 |
* |
| 1031 |
* @return if the system is shutting down |
| 1032 |
*/ |
| 1033 |
public static boolean isShuttingDown() { |
| 1034 |
return inShutdown; |
| 1035 |
} |
| 1036 |
|
| 1037 |
/** |
| 1038 |
* Gets the system exit code. |
| 1039 |
* |
| 1040 |
* @return the system exit code |
| 1041 |
*/ |
| 1042 |
public static int getExitCode() { |
| 1043 |
return exitCode; |
| 1044 |
} |
| 1045 |
|
| 1046 |
/** |
| 1047 |
* Halt the system. This method requires a JNodePermission("halt"). |
| 1048 |
* |
| 1049 |
* @param reset |
| 1050 |
*/ |
| 1051 |
@PrivilegedActionPragma |
| 1052 |
public static void halt(boolean reset) { |
| 1053 |
final SecurityManager sm = System.getSecurityManager(); |
| 1054 |
if (sm != null) { |
| 1055 |
sm.checkPermission(new JNodePermission("halt")); |
| 1056 |
} |
| 1057 |
exitCode = (reset ? 1 : 0); |
| 1058 |
inShutdown = true; |
| 1059 |
try { |
| 1060 |
final PluginManager pm = InitialNaming.lookup(PluginManager.NAME); |
| 1061 |
pm.stopPlugins(); |
| 1062 |
} catch (NameNotFoundException ex) { |
| 1063 |
System.err.println("Cannot find ServiceManager"); |
| 1064 |
} |
| 1065 |
} |
| 1066 |
|
| 1067 |
/** |
| 1068 |
* Set the effective System.in to a different InputStream. The actual behavior depends |
| 1069 |
* on whether we're in proclet mode or not. If we are, we set the appropriate proxied stream, |
| 1070 |
* to the new stream, depending on whether the current thread is a ProcletContext or not. |
| 1071 |
* Otherwise, we update the System.in field. |
| 1072 |
* |
| 1073 |
* @param in the new InputStream |
| 1074 |
* @see #setIn(InputStream) |
| 1075 |
*/ |
| 1076 |
@PrivilegedActionPragma |
| 1077 |
public static void setIn(InputStream in) { |
| 1078 |
getIOContext().setSystemIn(in); |
| 1079 |
} |
| 1080 |
|
| 1081 |
/** |
| 1082 |
* Set the effective System.out to a different PrintStream. The actual behavior depends |
| 1083 |
* on whether we're in proclet mode or not. If we are, we set the appropriate proxied stream, |
| 1084 |
* to the new stream, depending on whether the current thread is a ProcletContext or not. |
| 1085 |
* Otherwise, we update the System.out field. |
| 1086 |
* |
| 1087 |
* @param out the new PrintStream |
| 1088 |
* @see java.lang.System#setOut(PrintStream) |
| 1089 |
*/ |
| 1090 |
@PrivilegedActionPragma |
| 1091 |
public static void setOut(PrintStream out) { |
| 1092 |
getIOContext().setSystemOut(out); |
| 1093 |
} |
| 1094 |
|
| 1095 |
/** |
| 1096 |
* Set the effective System.err to a different PrintStream. The actual behavior depends |
| 1097 |
* on whether we're in proclet mode or not. If we are, we set the appropriate proxied stream, |
| 1098 |
* to the new stream, depending on whether the current thread is a ProcletContext or not. |
| 1099 |
* Otherwise, we update the System.err field. |
| 1100 |
* |
| 1101 |
* @param err the new PrintStream |
| 1102 |
* @see java.lang.System#setErr(PrintStream) |
| 1103 |
*/ |
| 1104 |
@PrivilegedActionPragma |
| 1105 |
public static void setErr(PrintStream err) { |
| 1106 |
getIOContext().setSystemErr(err); |
| 1107 |
} |
| 1108 |
|
| 1109 |
//todo protect this method from arbitrary access |
| 1110 |
@PrivilegedActionPragma |
| 1111 |
public static void setStaticField(Class<?> clazz, String fieldName, |
| 1112 |
Object value) { |
| 1113 |
final VmStaticField f = (VmStaticField) VmType.fromClass((Class<?>) clazz).getField( |
| 1114 |
fieldName); |
| 1115 |
final Object staticsTable; |
| 1116 |
final Offset offset; |
| 1117 |
if (f.isShared()) { |
| 1118 |
staticsTable = VmMagic.currentProcessor().getSharedStaticsTable(); |
| 1119 |
offset = Offset.fromIntZeroExtend(f.getSharedStaticsIndex() << 2); |
| 1120 |
} else { |
| 1121 |
staticsTable = VmMagic.currentProcessor().getIsolatedStaticsTable(); |
| 1122 |
offset = Offset.fromIntZeroExtend(f.getIsolatedStaticsIndex() << 2); |
| 1123 |
} |
| 1124 |
final Address ptr = VmMagic.getArrayData(staticsTable); |
| 1125 |
ptr.store(ObjectReference.fromObject(value), offset); |
| 1126 |
} |
| 1127 |
|
| 1128 |
//io context related |
| 1129 |
|
| 1130 |
public static IOContext getIOContext() { |
| 1131 |
return VmIsolate.currentIsolate().getIOContext(); |
| 1132 |
} |
| 1133 |
|
| 1134 |
public static boolean hasVmIOContext() { |
| 1135 |
return getIOContext() instanceof VmIOContext; |
| 1136 |
} |
| 1137 |
|
| 1138 |
|
| 1139 |
/** |
| 1140 |
* Get the current global (i.e. non-ProcletContext) flavor of System.err. |
| 1141 |
* |
| 1142 |
* @return the global 'err' stream. |
| 1143 |
*/ |
| 1144 |
public static PrintStream getGlobalErrStream() { |
| 1145 |
return VmIOContext.getGlobalErrStream(); |
| 1146 |
} |
| 1147 |
|
| 1148 |
/** |
| 1149 |
* Get the current global (i.e. non-ProcletContext) flavor of System.in. |
| 1150 |
* |
| 1151 |
* @return the global 'in' stream. |
| 1152 |
*/ |
| 1153 |
public static InputStream getGlobalInStream() { |
| 1154 |
return VmIOContext.getGlobalInStream(); |
| 1155 |
} |
| 1156 |
|
| 1157 |
/** |
| 1158 |
* Get the current global (i.e. non-ProcletContext) flavor of System.out. |
| 1159 |
* |
| 1160 |
* @return the global 'out' stream. |
| 1161 |
*/ |
| 1162 |
public static PrintStream getGlobalOutStream() { |
| 1163 |
return VmIOContext.getGlobalOutStream(); |
| 1164 |
} |
| 1165 |
|
| 1166 |
/** |
| 1167 |
* Switch the current Isolate from the initial IOContext to an external one. |
| 1168 |
* If the Isolate already has an external IOContext, this is a no-op. |
| 1169 |
* |
| 1170 |
* @param context |
| 1171 |
*/ |
| 1172 |
public static synchronized void switchToExternalIOContext(IOContext context) { |
| 1173 |
if (hasVmIOContext()) { |
| 1174 |
getIOContext().exitContext(); |
| 1175 |
VmIsolate.currentIsolate().setIOContext(context); |
| 1176 |
context.enterContext(); |
| 1177 |
} |
| 1178 |
} |
| 1179 |
|
| 1180 |
/** |
| 1181 |
* Reset to the current Isolate to its initial IOContext. |
| 1182 |
*/ |
| 1183 |
public static synchronized void resetIOContext() { |
| 1184 |
if (!hasVmIOContext()) { |
| 1185 |
getIOContext().exitContext(); |
| 1186 |
VmIsolate.currentIsolate().resetIOContext(); |
| 1187 |
getIOContext().enterContext(); |
| 1188 |
} else { |
| 1189 |
throw new RuntimeException("IO Context cannot be reset"); |
| 1190 |
} |
| 1191 |
} |
| 1192 |
} |