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方法,但是实现逻辑上应该是类似反射修改变量之类的

 

posted @ 2020-08-03 15:49  大哥超帅  阅读(634)  评论(0编辑  收藏  举报