public final static PrintStream out = null; 的实例化猜想
Java的控制台输出 System.out.println 以效率慢,调用简便闻名,但是在源码中out被static final 修饰,怎么把这个对象赋值呢?
system中有以下代码块
/* register the natives via the static initializer. * * VM will invoke the initializeSystemClass method to complete * the initialization for this class separated from clinit. * Note that to use properties set by the VM, see the constraints * described in the initializeSystemClass method. */ private static native void registerNatives(); static { registerNatives(); }
意思是说该native是要让vm 'invoke ' 调用 initializeSystemClass 方法 java里的invoke 懂得都懂
/** * Initialize the system class. Called after thread initialization. */ private static void initializeSystemClass() { // VM might invoke JNU_NewStringPlatform() to set those encoding // sensitive properties (user.home, user.name, boot.class.path, etc.) // during "props" initialization, in which it may need access, via // System.getProperty(), to the related system encoding property that // have been initialized (put into "props") at early stage of the // initialization. So make sure the "props" is available at the // very beginning of the initialization and all system properties to // be put into it directly. props = new Properties(); initProperties(props); // initialized by the VM // There are certain system configurations that may be controlled by // VM options such as the maximum amount of direct memory and // Integer cache size used to support the object identity semantics // of autoboxing. Typically, the library will obtain these values // from the properties set by the VM. If the properties are for // internal implementation use only, these properties should be // removed from the system properties. // // See java.lang.Integer.IntegerCache and the // sun.misc.VM.saveAndRemoveProperties method for example. // // Save a private copy of the system properties object that // can only be accessed by the internal implementation. Remove // certain system properties that are not intended for public access. sun.misc.VM.saveAndRemoveProperties(props); lineSeparator = props.getProperty("line.separator"); sun.misc.Version.init(); FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err); setIn0(new BufferedInputStream(fdIn)); setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding"))); setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding"))); // Load the zip library now in order to keep java.util.zip.ZipFile // from trying to use itself to load this library later. loadLibrary("zip"); // Setup Java signal handlers for HUP, TERM, and INT (where available). Terminator.setup(); // Initialize any miscellenous operating system settings that need to be // set for the class libraries. Currently this is no-op everywhere except // for Windows where the process-wide error mode is set before the java.io // classes are used. sun.misc.VM.initializeOSEnvironment(); // The main thread is not added to its thread group in the same // way as other threads; we must do it ourselves here. Thread current = Thread.currentThread(); current.getThreadGroup().add(current); // register shared secrets setJavaLangAccess(); // Subsystems that are invoked during initialization can invoke // sun.misc.VM.isBooted() in order to avoid doing things that should // wait until the application class loader has been set up. // IMPORTANT: Ensure that this remains the last initialization action! sun.misc.VM.booted(); }
引用知乎大佬的一段关于反射修改final的解释
作者:Accelerator 链接:https://www.zhihu.com/question/47054187/answer/127690274 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 泻药被final修饰过的变量,只是说栈存储的地址不能再改变,但是却没有说地址指向的内容不能改变,所以反射可以破final,因为它修改该了以前地址的具体内容,但是没有改地址的信息。
举个例子:一个路段,只允许牌子为10000的车过,但是并没有说不允许套牌。牌子还是10000但是车变了。然后被static修饰的变量也能修改,
同样道理,只不过第一个参数为null。但是同时被final和static变量修饰的就不能被修改了,会抛出异常,在jdk的doc(Field (Java Platform SE 7 )中有描述至于能不能修改
,肯定能,因为@唐小狸已经给出了答案。
field = Comtest.class.getDeclaredField("value1"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field,field.getModifiers()&~Modifier.FINAL); field.set(null, new char[]{'1', '2', '3'}); field.getModifiers()&~Modifier.FINAL 这句话就是去掉final。其实java的访问权限信息啥的都是以2的N次幂来作为表示的,具体都是在java.lang.reflect.Modifier这个类里。
getModifiers()&~Modifier.FINAL 具体看下问运算,如果有(111111&000000=000000.)抹去了16这个final标识。不行了,我大人叫我去吃饭了,,闪了////////////
我的猜想就是虚拟机明面上用了native方法,但是实现逻辑上应该是类似反射修改变量之类的