首先静态域与网络传输没有关系,静态域不可以被序列化,也不会在网络中被传输。我们先通过一个例子验证这个问题,后面再分析静态域到底是怎样的一种存在。
以下是一个socket通信过程,Client端负责实例的构造和发送,Server端负责监听和接收来自端口的实例,User类拥有静态变量和成员变量,这里将User的实例作为目标进行传输。
import java.io.*; import java.net.Socket; /** * User: zzzz76 * Date: 2018-07-07 */ public class Client { public static void main(String[] args) throws Exception { User.setTag("client"); for (int i = 0; i < 5; i++) { Socket socket = null; BufferedOutputStream bos = null; ObjectOutputStream oos = null; try { socket = new Socket("localhost", 10000); bos = new BufferedOutputStream(socket.getOutputStream()); oos = new ObjectOutputStream(bos); User user = new User("user_" + i, "password_" + i); oos.writeObject(user); oos.flush(); } catch (IOException ex) { ex.printStackTrace(); } finally { IOUtils.closeQuietly(oos); IOUtils.closeQuietly(bos); IOUtils.closeQuietly(socket); } } } }
import java.io.*; import java.net.ServerSocket; import java.net.Socket; /** * User: zzzz76 * Date: 2018-07-07 */ public class Server { public static void main(String[] args) { User.setTag("server"); ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(10000); serverSocket.setSoTimeout(10000); // Listen for the connection to accept socket while (true) { Socket socket = serverSocket.accept(); launch(socket); } } catch (IOException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(serverSocket); } } /** * Launch socket to receive the input of task * * @param socket */ private static void launch(Socket socket) { new Thread(() -> { BufferedInputStream bis = null; ObjectInputStream ois = null; try { bis = new BufferedInputStream(socket.getInputStream()); ois = new ObjectInputStream(bis); Object obj = ois.readObject(); User user = (User) obj; System.out.println("Get socket user: " + user.getTag() + "/" + user.getName() + "/" + user.getPassword()); } catch (IOException | ClassNotFoundException ex) { ex.printStackTrace(); } finally { IOUtils.closeQuietly(ois); IOUtils.closeQuietly(bis); IOUtils.closeQuietly(socket); } }).start(); } }
import java.io.Serializable; /** * User: zzzz76 * Date: 2018-07-07 */ public class User implements Serializable { //类加载时在方法区分配内存,并初始化 private static String tag = "clinit"; static { System.out.println("Init static tag: " + tag); } private String name; private String password; //构造实例时在堆上分配内存,并初始化 public User() { System.out.println("Init instance user"); } public User(String name, String password) { this.name = name; this.password = password; System.out.println("Init Instance user: " + name + "/" +password); } public String getName() { return name; } public User setName(String name) { this.name = name; return this; } public String getPassword() { return password; } public User setPassword(String password) { this.password = password; return this; } public static String getTag() { return tag; } public static void setTag(String tag) { System.out.println("Update static tag: " + tag); User.tag = tag; } }
输出结果:
➜ Desktop java Client Init static tag: clinit Update static tag: client Init Instance user: user_0/password_0 Init Instance user: user_1/password_1 Init Instance user: user_2/password_2 Init Instance user: user_3/password_3 Init Instance user: user_4/password_4
➜ Desktop java Server Init static tag: clinit Update static tag: server Get socket user: server/user_2/password_2 Get socket user: server/user_3/password_3 Get socket user: server/user_4/password_4 Get socket user: server/user_0/password_0 Get socket user: server/user_1/password_1
从输出结果可以看出:
- 在Server端中,User的构造函数没有经过调用,说明User实例是从端口处获取的。
- 静态域在传输开始之前就已经产生并且经过初始化,每一个User实例都指向位于本JVM进程中的静态域,而并非网络端口(其他JVM进程),所以静态域没有到参与整个传输过程中。
其实这里产生了两个JVM实例,每个实例都具有独立的堆栈,其中静态域就位于堆栈的方法区中。User实例在不同的JVM实例上指向不同的静态域,导致通信前后静态变量的不同。关于静态域和类加载的过程可以看看我的上篇文章。
来源:https://www.cnblogs.com/zzzz76/p/9338671.html