Java安全模型(沙箱or策略)和transient变量


在研究enum类的源码时,跟踪到Class类的如下代码:

T[] getEnumConstantsShared() {
        if (enumConstants == null) {
            if (!isEnum()) return null;
            try {
                final Method values = getMethod("values");
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction<Void>() {
                        public Void run() {
                                values.setAccessible(true);
                                return null;
                            }
                        });
                enumConstants = (T[])values.invoke(null);
            }
            // These can happen when users concoct enum-like classes
            // that don't comply with the enum spec.
            catch (InvocationTargetException ex) { return null; }
            catch (NoSuchMethodException ex) { return null; }
            catch (IllegalAccessException ex) { return null; }
        }
        return enumConstants;
    }
    private volatile transient T[] enumConstants = null;

在上述代码中有两处标红的代码:

1、java.security.AccessController.doPrivileged...这段代码可参考:《基于 Java 2 运行时安全模型的线程协作》 http://www.ibm.com/developerworks/cn/java/j-lo-rtsecurity/

可惜看完一遍还是晕菜,什么必须要签名之类的,平时也没有遇到过啊,汗啊~~~

2、volatile是解决线程可见性问题的,transient是临时性的变量不会被串行化。

transient的问题可参考如下的代码:

package com.study.java.core.serializable;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

import com.study.java.core.Employee;

public class Person implements Serializable{
    private transient Employee employee=null;
    private String id=null;
    private transient String pwd=null;
    
    public Person( Employee employee ){
        this.employee=employee;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
    
    @Override
    public String toString() {
        return this.getClass().getName()+":id="+id+",pwd="+pwd+",employee:"+employee;
    }
    public static void main(String[] args) {
        Employee employee=new Employee();
        employee.setId("员工1");
        employee.setName("员工姓名");
        Person person=new Person(employee);
        person.setId("001");
        person.setPwd("password");
        
        try {
            OutputStream os=new FileOutputStream("f:"+File.separator+"a.txt");
            ObjectOutputStream oos=new ObjectOutputStream(os);
            oos.writeObject(person);
            oos.flush();
            oos.close();
            InputStream is=new FileInputStream("f:"+File.separator+"a.txt");
            ObjectInputStream ois=new ObjectInputStream(is);
            Person person1=(Person)ois.readObject();
            
            System.out.println(person1.toString());
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

从输出结果可以看出:pwd和employee都为null,因为它们都被设置为transient 

本文永久更新链接地址

相关内容