第十四行打印的是Field对象的modifiers的值,跟那个_isCreatePool有什么关系?掩耳盗铃?
           System.out.println("修改后:"+Modifier.toString(this.getClass().getDeclaredField("_isCreatePool").getModifiers()));
 

解决方案 »

  1.   

    我在二楼说错了。找到问题了,1.反射对修改基本类型好像不起作用吧?如果封装成Boolean对象可以修改成功。2.如果是非静态final成员,就不需要修改field的modifiers的值直接set一个value,如果修改静态final成员就必须修改Field对象的modifiers的值,否则抛出java.lang.IllegalAccessException(这是什么sun.reflect.UnsafeQualifiedStaticFieldAccessorImpl)?不解。3.是否field.set(obj,  value)时要检查field对象自己的modifiers值,而并不是真的修改了指定字段的访问性。以上问题还得探索下。
      

  2.   


    第一点:我做个实验试试 
    第二点:这是设计的一个方式问题,final , 是因为我已经 public ! 这是我想要final的原因!而不是setter !
    第三点:是您自己的观点或估计,还是既成事实 ?我想知道,有否证明 !
      

  3.   

    对反射研究不深,稍微补充了下你的代码:    public static void main(String[] args) throws SecurityException, IllegalArgumentException, ClassNotFoundException,
                NoSuchFieldException, IllegalAccessException {
            MainTest m = new MainTest();
            System.out.println("这是_isCreatePool被改变之前的值:" + m._isCreatePool);
            m._isCreatePool = true;
            m.test(m._isCreatePool);
            m._isCreatePool = false;
            System.out.println((m._isCreatePool) ? "没改变,依然是true"
                    : "值被改变了,说明反射字符_isCreatePool,将_isCreatePool的修饰符改为final失败了,无效,此时,结果由true为false");
            m.check();// 这里增加一个方法,再次检测
        }    // 这里增加一个方法,再次检测
        public void check() throws SecurityException, NoSuchFieldException {
            Field _isCreatePoolField = this.getClass().getDeclaredField("_isCreatePool");
            System.out.println("再次检测:" + Modifier.toString(_isCreatePoolField.getModifiers()));
        }最后返回还是Public,感觉应该是修改final有作用域的。
    部分核心Security检测的代码没有给源码,不好瞎说。不是说有了反射,就一定要破坏类的方位权限、作用域,而且你钻的还挺深的。
    兄弟,别太钻牛角尖哈~
      

  4.   

    顶楼上,你在test方法中试着改变_isCreatePool属性值看会不会抛出异常。
      

  5.   

    这个还是不会异常,猜测final是编译期做安全校验的,过了编译期,就不再校验这个了。
      

  6.   


    这又是对Java 基础了解不深引起的。你在m.test(m._isCreatePool) ;  后加上System.out.println(Modifier.toString(m.getClass().getField("_isCreatePool").getModifiers())); 测试下。
    保证你有惊奇的发现;其实,你只要了解下JVM的类加载机制就知道了;
    简单说是,在一个类加载器中,类只会加载一次,也就是你的JVM内存中还是原来的类的类型信息;所以你上面修改_isCreatePool的访问修饰符,而不重新编译加载新类,和你改了一个类不重新编译再运行,有什么区别;    
      

  7.   

    Quote: 引用 楼主 weidu23 的回复:

             有一天,自己突然奇想,假定有一个值 public boolean flag = false ; 一旦他被赋值为true ,那么,我就反射将其final !这样的话,在不考虑安全管理器的情况下,除非反射,否则是改不了其值的 !
    Quote:

    除了反射,还是能直接改的
             
      

  8.   

    因为jdk有些源码没公开,果断下载openjdk源码。我调试跟踪了下,原来当field.getModifiers()为static final时肯定是只读的。所以后来getFieldAccessor(obj).set(obj, value);会抛出异常。/*
     * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved.
     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     *
     * This code is free software; you can redistribute it and/or modify it
     * under the terms of the GNU General Public License version 2 only, as
     * published by the Free Software Foundation.  Oracle designates this
     * particular file as subject to the "Classpath" exception as provided
     * by Oracle in the LICENSE file that accompanied this code.
     *
     * This code is distributed in the hope that it will be useful, but WITHOUT
     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     * version 2 for more details (a copy is included in the LICENSE file that
     * accompanied this code).
     *
     * You should have received a copy of the GNU General Public License version
     * 2 along with this work; if not, write to the Free Software Foundation,
     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     *
     * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     * or visit www.oracle.com if you need additional information or have any
     * questions.
     */package sun.reflect;import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;class UnsafeFieldAccessorFactory {
        static FieldAccessor newFieldAccessor(Field field, boolean override) {
            Class type = field.getType();
            boolean isStatic = Modifier.isStatic(field.getModifiers());
            boolean isFinal = Modifier.isFinal(field.getModifiers());
            boolean isVolatile = Modifier.isVolatile(field.getModifiers());
            boolean isQualified = isFinal || isVolatile;
            boolean isReadOnly = isFinal && (isStatic || !override);
            if (isStatic) {
                // This code path does not guarantee that the field's
                // declaring class has been initialized, but it must be
                // before performing reflective operations.
                UnsafeFieldAccessorImpl.unsafe.ensureClassInitialized(field.getDeclaringClass());            if (!isQualified) {
                    if (type == Boolean.TYPE) {
                        return new UnsafeStaticBooleanFieldAccessorImpl(field);
                    } else if (type == Byte.TYPE) {
                        return new UnsafeStaticByteFieldAccessorImpl(field);
                    } else if (type == Short.TYPE) {
                        return new UnsafeStaticShortFieldAccessorImpl(field);
                    } else if (type == Character.TYPE) {
                        return new UnsafeStaticCharacterFieldAccessorImpl(field);
                    } else if (type == Integer.TYPE) {
                        return new UnsafeStaticIntegerFieldAccessorImpl(field);
                    } else if (type == Long.TYPE) {
                        return new UnsafeStaticLongFieldAccessorImpl(field);
                    } else if (type == Float.TYPE) {
                        return new UnsafeStaticFloatFieldAccessorImpl(field);
                    } else if (type == Double.TYPE) {
                        return new UnsafeStaticDoubleFieldAccessorImpl(field);
                    } else {
                        return new UnsafeStaticObjectFieldAccessorImpl(field);
                    }
                } else {
                    if (type == Boolean.TYPE) {
                        return new UnsafeQualifiedStaticBooleanFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Byte.TYPE) {
                        return new UnsafeQualifiedStaticByteFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Short.TYPE) {
                        return new UnsafeQualifiedStaticShortFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Character.TYPE) {
                        return new UnsafeQualifiedStaticCharacterFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Integer.TYPE) {
                        return new UnsafeQualifiedStaticIntegerFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Long.TYPE) {
                        return new UnsafeQualifiedStaticLongFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Float.TYPE) {
                        return new UnsafeQualifiedStaticFloatFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Double.TYPE) {
                        return new UnsafeQualifiedStaticDoubleFieldAccessorImpl(field, isReadOnly);
                    } else {
                        return new UnsafeQualifiedStaticObjectFieldAccessorImpl(field, isReadOnly);
                    }
                }
            } else {
                if (!isQualified) {
                    if (type == Boolean.TYPE) {
                        return new UnsafeBooleanFieldAccessorImpl(field);
                    } else if (type == Byte.TYPE) {
                        return new UnsafeByteFieldAccessorImpl(field);
                    } else if (type == Short.TYPE) {
                        return new UnsafeShortFieldAccessorImpl(field);
                    } else if (type == Character.TYPE) {
                        return new UnsafeCharacterFieldAccessorImpl(field);
                    } else if (type == Integer.TYPE) {
                        return new UnsafeIntegerFieldAccessorImpl(field);
                    } else if (type == Long.TYPE) {
                        return new UnsafeLongFieldAccessorImpl(field);
                    } else if (type == Float.TYPE) {
                        return new UnsafeFloatFieldAccessorImpl(field);
                    } else if (type == Double.TYPE) {
                        return new UnsafeDoubleFieldAccessorImpl(field);
                    } else {
                        return new UnsafeObjectFieldAccessorImpl(field);
                    }
                } else {
                    if (type == Boolean.TYPE) {
                        return new UnsafeQualifiedBooleanFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Byte.TYPE) {
                        return new UnsafeQualifiedByteFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Short.TYPE) {
                        return new UnsafeQualifiedShortFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Character.TYPE) {
                        return new UnsafeQualifiedCharacterFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Integer.TYPE) {
                        return new UnsafeQualifiedIntegerFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Long.TYPE) {
                        return new UnsafeQualifiedLongFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Float.TYPE) {
                        return new UnsafeQualifiedFloatFieldAccessorImpl(field, isReadOnly);
                    } else if (type == Double.TYPE) {
                        return new UnsafeQualifiedDoubleFieldAccessorImpl(field, isReadOnly);
                    } else {
                        return new UnsafeQualifiedObjectFieldAccessorImpl(field, isReadOnly);
                    }
                }
            }
        }
    }
      

  9.   


    您说不是反射,那么请问,您这里,是怎么处理呢?求教上面给你说了下 要去了解类加载机制;你若了解 Java中的对象拷贝原理,结合上面的说的,应该是完全明白了;其实就是这条语句:
     Field _isCreatePoolField = this.getClass().getDeclaredField("_isCreatePool") ; 
    返回的是Field对象的一个副本,你怎么改都不会影响原来的对象;
      

  10.   


    您说不是反射,那么请问,您这里,是怎么处理呢?求教上面给你说了下 要去了解类加载机制;你若了解 Java中的对象拷贝原理,结合上面的说的,应该是完全明白了;其实就是这条语句:
     Field _isCreatePoolField = this.getClass().getDeclaredField("_isCreatePool") ; 
    返回的是Field对象的一个副本,你怎么改都不会影响原来的对象;1、类加载器,在我现在的思维里,无非就是类被初始调度时,赋值而已,不知理解错了么?
    2、你说现在改变的是副本,那要怎么才能拿到原来的对象 ?
      

  11.   

    不清楚你什么Java水平,若是工作了个2、3年,基本上知道上面的术语意思,一说应该就明白什么意思了;最后简单说下:
    1、 要你去了解 JVM 的类加载机制,是因为这个过程会产生一个表示加载类的一个Class对象,而 反射 获取就是这些 Class实例 表示的 类的信息;
    若自己确实想学习,从这里就可以去了解虚拟机的执行子系统,虚拟机的内存结构,虚拟机的内存管理机制 等内容了;
    2、通过Java API拿不到Field原来的对象;所有Class.getFields(), Class.getField(String), Class.getDeclaredFields(), Class.getDeclaredField(String)都是返回Field的 copy对象;为什么,源代码就是这么写的;(为啥不把源代码贴出来,自己把JDK下的那个src.zip 导入,就可以自己看了);
    上面提到了Java中对象的copy机制,若也想学习,就可以去了解下什么是深拷贝、浅拷贝;
      

  12.   

    不清楚你什么Java水平,若是工作了个2、3年,基本上知道上面的术语意思,一说应该就明白什么意思了;最后简单说下:
    1、 要你去了解 JVM 的类加载机制,是因为这个过程会产生一个表示加载类的一个Class对象,而 反射 获取就是这些 Class实例 表示的 类的信息;
    若自己确实想学习,从这里就可以去了解虚拟机的执行子系统,虚拟机的内存结构,虚拟机的内存管理机制 等内容了;
    2、通过Java API拿不到Field原来的对象;所有Class.getFields(), Class.getField(String), Class.getDeclaredFields(), Class.getDeclaredField(String)都是返回Field的 copy对象;为什么,源代码就是这么写的;(为啥不把源代码贴出来,自己把JDK下的那个src.zip 导入,就可以自己看了);
    上面提到了Java中对象的copy机制,若也想学习,就可以去了解下什么是深拷贝、浅拷贝;恩 !可能您误会我的意思了 。
    1、类加载,必然是在调度时候才加载,只是rt.jar等等在固定目录的文件中的class才会被提前加载。
    我刚刚指的是:final除了在定义时候可以被赋值,还可以在定义不赋值,而在构造器中赋值,所以我才所说【无非就是类被初始调度时,赋值而已】 。
    但是,我不理解的是,您说【除了反射,还是能直接改的 】!
    2、clone的话,我不是常用,因为我目前很少用到它,我用到它的场景不多,对于何种场景被用到不熟悉,所以,请指教!
      

  13.   

    “public boolean”去掉public修饰符