文档库 最新最全的文档下载
当前位置:文档库 › Java存储模型和共享对象

Java存储模型和共享对象

Java存储模型和共享对象
Java存储模型和共享对象

Java存储模型和共享对象

很多程序员对一个共享变量初始化要注意可见性和安全发布(安全地构建一个对象,并其他线程能正确访问)等问题不是很理解,认为Java是一个屏蔽内存细节的平台,连对象回收都不需要关心,因此谈到可见性和安全发布大多不知所云。其实关键在于对Java存储模型,可见性和安全发布的问题是起源于 Java的存储结构。

Java存储模型原理

有很多书和文章都讲解过Java存储模型,其中一个图很清晰地说明了其存储结构:

由上图可知, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。

这个存储模型很像我们常用的缓存与数据库的关系,因此由此可以推断JVM如此设计应该是为了提升性能,提高多线程的并发能力,并减少线程之间的影响。

Java存储模型潜在的问题

一谈到缓存,我们立马想到会有缓存不一致性问题,就是说当有缓存与数据库不一致的时候,就需要有相应的机制去同步数据。同理,Java存储模型也有这个问题,当一个线程在自己工作内存里初始化一个变量,当还没来得及同步到主存里时,如果有其他线程来访问它,就会出现不可预知的问题。另外,JVM在底层设计上,对与那些没有同步到主存里的变量,可能会以不一样的操作顺序来执行指令,举个实际的例子:

1.public class PossibleReordering {

2. static int x = 0, y = 0;

3. static int a = 0, b = 0;

4. public static void main(String[] args)

5. throws InterruptedException {

6. Thread one = new Thread(new Runnable() {

7. public void run() {

8. a = 1;

9. x = b;

10. }

11. });

12. Thread other = new Thread(new Runnable() {

13. public void run() {

14. b = 1;

15. y = a;

16. }

17. });

18. one.start(); other.start();

19. one.join(); other.join();

20. System.out.println("( "+ x + "," + y + ")");

21. }

22.}

由于,变量x,y,a,b没有安全发布,导致会不以规定的操作顺序来执行这次四次赋值操作,有可能出现以下顺序:

出现这个问题也可以理解,因为既然这些对象不可见,也就是说本应该隔离在各个线程的工作区内,那么对于有些无关顺序的指令,打乱顺序执行在JVM看来也是可行的。

因此,总结起来,会有以下两种潜在问题:

?缓存不一致性

?重排序执行

解决Java存储模型潜在的问题

为了能让开发人员安全正确地在Java存储模型上编程,JVM提供了一个happens-before原则,有人整理得非常好,我摘抄如下:

?在程序顺序中, 线程中的每一个操作, 发生在当前操作后面将要出现的每一个操作之前.

?对象监视器的解锁发生在等待获取对象锁的线程之前.

?对volitile关键字修饰的变量写入操作, 发生在对该变量的读取之前.

?对一个线程的 Thread.start() 调用发生在启动的线程中的所有操作之前.

?线程中的所有操作发生在从这个线程的 Thread.join()成功返回的所有其他线程之前.

有了原则还不够,Java提供了以下工具和方法来保证变量的可见性和安全发布:?使用 synchronized来同步变量初始化。此方式会立马把工作内存中的变量同步到主内存中

?使用 volatile关键字来标示变量。此方式会直接把变量存在主存中而不是工作内存中

?final变量。常量内也是存于主存中

另外,一定要明确只有共享变量才会有以上那些问题,如果变量只是这个线程自己使用,就不用担心那么多问题了

搞清楚Java存储模型后,再来看共享对象可见性和安全发布的问题就较为容易了

共享对象的可见性

当对象在从工作内存同步到主内存之前,那么它就是不可见的。若有其他线程在存取不可见对象就会引发可见性问题,看下面一个例子:

1.public class NoVisibility {

2. private static boolean ready;

3. private static int number;

4. private static class ReaderThread extends Thread {

5. public void run() {

6. while (!ready)

7. Thread.yield();

8. System.out.println(number);

9. }

10. }

11. public static void main(String[] args) {

12. new ReaderThread().start();

13. number = 42;

14. ready = true;

15. }

16.}

按照正常逻辑,应该会输出42,但其实际结果会非常奇怪,可能会永远没有输出(因为ready为false),可能会输出0(因为重排序问题导致ready=true先执行)。再举一个更为常见的例子,大家都喜欢用只有set 和get方法的pojo来设计领域模型,如下所示:

1.@NotThreadSafe

2.public class MutableInteger {

3. private int value;

4. public int get() { return value; }

5. public void set(int value) { this.value = value; }

6.}

但是,当有多个线程同时来存取某一个对象时,可能就会有类似的可见性问题。

为了保证变量的可见性,一般可以用锁、 synchronized关键字、 volatile关键字或直接设置为final

共享变量发布

共享变量发布和我们常说的发布程序类似,就是说让本属于内部的一个变量变为一个可以被外部访问的变量。发布方式分为以下几种:

?将对象引用存储到公共静态域

?初始化一个可以被外部访问的对象

?将对象引用存储到一个集合里

安全发布和保证可见性的方法类似,就是要同步发布动作,并使发布后的对象可见。

线程安全

其实当我们把这些变量封闭在本线程内访问,就可以从根本上避免以上问题,现实中存在很多例子通过线程封闭来安全使用本不是线程安全的对象,比如:

?swing的可视化组件和数据模型对象并不是线程安全的,它通过将它们限制到swing的事件分发线程中,实现线程安全

?JDBC Connection对象没有要求为线程安全,但JDBC的存取模式决定了一个Connection只会同时被一个线程使用

?ThreadLocal把变量限制在本线程中共享

java技术面试必问:JVM 内存模型讲解

java技术面试必问:JVM 内存模型讲解 今天我们就来聊一聊Java内存模型,面试中面试官会通过考察你对jvm的理解更深入得了解你的水平。在了解jvm内存模型前我们先回顾下,java程序的执行过程: java文件在通过java编译器生产.class 字节码文件,然后由jvm中的类加载器加载各个类中的字节码文件,加载完成后由jvm执行引擎执行,在整个加载过程中,jvm用一段空间来存储程序执行期间需要的数据和相关信息,这个空间就叫做jvm内存。 一、JVM 的重要性 首先你应该知道,运行一个 Java 应用程序,我们必须要先安装 JDK 或者 JRE 。这是因为 Java 应用在编译后会变成字节码,然后通过字节码运行在 JVM 中,而 JVM 是JRE 的核心组成部分。 二、优点 JVM 不仅承担了 Java 字节码的分析(JIT compiler)和执行(Runtime),同时也内置了自动内存分配管理机制。这个机制可以大大降低手动分配回收机制可能带来的内存泄露和内存溢出风险,使 Java 开发人员不需要关注每个对象的内存分配以及回收,从而更专注于业务本身。 三、缺点 这个机制在提升 Java 开发效率的同时,也容易使 Java 开发人员过度依赖于自动化,弱化对内存的管理能力,这样系统就很容易发生 JVM 的堆内存异常、垃圾回收(GC)的不合适以及 GC 次数过于频繁等问题,这些都将直接影响到应用服务的性能。 四、内存模型 JVM 内存模型共分为5个区:堆(Heap)、方法区(Method Area)、程序计数器(Program Counter Register)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack)。 其中,堆(Heap)、方法区(Method Area)为线程共享,程序计数器(Program Counter Register)、虚拟机栈(VM Stack)、本地方法栈(Native Method Stack)为线程隔离。 五、堆(Heap) 堆是 JVM 内存中最大的一块内存空间,该内存被所有线程共享,几乎所有对象和数组都被分配到了堆内存中。 堆被划分为新生代和老年代,新生代又被进一步划分为 Eden 区和 Survivor 区,最后 Survivor 由 From Survivor 和 To Survivor 组成。

java序列化的作用

最近在阅读Core J2EE Patterns 的时候发现例子里用于在各个层次里进行传输的TO(Data Transfer Object)都实现了java.io.Serializable接口,看到这些偶突然感到茅塞顿开~困扰了很久的关于Serializable的疑问渐渐解开了,查找相关资料并总结如下: 序列化是什么: 序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得。 序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例 序列化的什么特点: 如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态, transient代表对象的临时数据。 什么时候使用序列化: 一:对象序列化可以实现分布式对象。主要应用例如:RMI要利用对象序列化运行远程主机上的服务,就像在本地机上运行对象时一样。 二:java对象序列化不仅保留一个对象的数据,而且递归保存对象引用的每个对象的数据。可以将整个对象层次写入字节流中,可以保存在文件中或在网络连接上传递。利用对象序列化可以进行对象的"深复制",即复制对象本身及引用的对象本身。序列化一个对象可能得到整个对象序列。 ====================== 可以看看接口java.io.serializable的中文解释: Serializable public interface Serializable 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。

java数据在内存中存储详解

博客分类: JAVA 1. 有这样一种说法,如今争锋于IT战场的两大势力,MS一族偏重于底层实现,Java 一族偏重于系统架构。说法根据无从考证,但从两大势力各自的社区力量和图书市场已有佳作不难看出,此说法不虚,但掌握Java的底层实现对Java程序员来说是至关重要的,本文介绍了Java中的数据在内存中的存储。 2内存中的堆(stack)与栈(heap) Java程序运行时有6个地方可以存储数据,它们分别是寄存器、栈、堆、静态存储、常量存储和非RAM存储,主要是堆与栈的存储。 【随机存储器:Random Access Memory】 栈与堆都是Java用来在RAM中存放数据的地方。与C++不同,Java自动管理栈和堆,程序员不能直接地设置栈或堆。栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器。另外,栈数据可以共享。但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。 【寄存器位于CPU中】 3Java中数据在内存中的存储 3.1基本数据类型的存储 Java的基本数据类型共有8种,即int,short,long,byte,float,double, boolean,char(注意,并没有string的基本类型)。这种类型的定义是通过诸如int a=3;long b=255L;的形式来定义的,称为自动变量。值得注意的是:自动变量存的是字面值,不是类的实例,即不是类的引用,这里并没有类的存在。如int a=3;这里的a是一个指向int类型的引用,指向3这个字面值。这些字面值的数据,由于大小可知,生存期可知(这些字面值固定定义在某个程序块里面,程序块退出后,字段值就消失了),出于追求速度的原因,就存在于栈中。

java内存屏障与JVM并发详解

深入Java底层:内存屏障与JVM并发详解(1) 本文介绍了内存屏障对多线程程序的影响,同时将研究内存屏障与JVM并发机制的关系,如易变量(volatile)、同步(synchronized)和原子条件式(atomic conditional)。 AD:内存屏障,又称内存栅栏,是一组处理器指令,用于实现对内存操作的顺序限制。本文假定读者已经充分掌握了相关概念和Java内存模型,不讨论并发互斥、并行机制和原子性。内存屏障用来实现并发编程中称为可见性(visibility)的同样重要的作用。 关于JVM更多内容,请参阅:JVM详解 Java虚拟机原理与优化 内存屏障为何重要? 对主存的一次访问一般花费硬件的数百次时钟周期。处理器通过缓存(caching)能够从数量级上降低内存延迟的成本这些缓存为了性能重新排列待定内存操作的顺序。也就是说,程序的读写操作不一定会按照它要求处理器的顺序执行。当数据是不可变的,同时/或者数据限制在线程范围内,这些优化是无害的。 如果把这些优化与对称多处理(symmetric multi-processing)和共享可变状态(shared mutable state)结合,那么就是一场噩梦。当基于共享可变状态的内存操作被重新排序时,程序可能行为不定。一个线程写入的数据可能被其他线程可见,原因是数据写入的顺序不一致。适当的放置内存屏障通过强制处理器顺序执行待定的内存操作来避免这个问题。 内存屏障的协调作用 内存屏障不直接由JVM暴露,相反它们被JVM插入到指令序列中以维持语言层并发原语的语义。我们研究几个简单Java程序的源代码和汇编指令。首先快速看一下Dekker算法中的内存屏障。该算法利用volatile变量协调两个线程之间的共享资源访问。 请不要关注该算法的出色细节。哪些部分是相关的?每个线程通过发信号试图进入代码第一行的关键区域。如果线程在第三行意识到冲突(两个线程都要访问),通过turn变量的操作来解决。在任何时刻只有一个线程可以访问关键区域。 1. // code run by first thread // code run by second thread 2. 3. 1 intentFirst = true; intentSecond = true;

JAVA序列化基础知识Serializable与Externalizable的区别

大家都知道Serializable是一个mark interface,告诉JVM这个对象可以被转换成二进制流来传输. 但是Serializable与Externalizable的转换二进制流的过程是不一样的. Serializable 在我们实现这个接口的时候,我们可以使用4个私有方法来控制序列化的过程: 我们来看一个例子: public class FooImpl implements java.io.Serializable{ private String message; public String getFoo() { return message; } public void setMessage(String message) { this.message = message; } private void writeObject(java.io.ObjectOutputStream out) throws IOException { System.out.println("writeObject invoked"); out.writeObject(this.message == null ? "hohohahaha" : this.message); } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { System.out.println("readObject invoked"); this.message = (String) in.readObject(); System.out.println("got message:" + message); } private Object writeReplace() throws ObjectStreamException { System.out.println("writeReplace invoked"); return this; } private Object readResolve() throws ObjectStreamException { System.out.println("readResolve invoked"); return this; }

Java内存区域划分、内存分配原理

本文由我司收集整编,推荐下载,如有疑问,请与我司联系 Java 内存区域划分、内存分配原理 2014/11/16 2448 运行时数据区域 Java 虚拟机在执行Java 的过程中会把管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程 的启动而存在,而有的区域则依赖线程的启动和结束而创建和销毁。 Java 虚拟机包括下面几个运行时数据区域: 程序计数器 程序计数器是一块较小的区域,它的作用可以看做是当前线程所执行的字节码的行号指示器。在虚拟机的模型里,字节码指示器就是通过改变程序计数器的值 来指定下一条需要执行的指令。分支,循环等基础功能就是依赖程序计数器来完成的。 由于java 虚拟机的多线程是通过轮流切换并分配处理器执行时间来完成,一个处理器同一时间只会执行一条线程中的指令。为了线程恢复后能够恢复正确的 执行位置,每条线程都需要一个独立的程序计数器,以确保线程之间互不影响。因 此程序计数器是“线程私有”的内存。 如果虚拟机正在执行的是一个Java 方法,则计数器指定的是字节码指令对应的地址,如果正在执行的是一个本地方法,则计数器指定问空undefined。程序计数器区域是Java 虚拟机中唯一没有定义OutOfMemory 异常的区域。 Java 虚拟机栈 和程序计数器一样也是线程私有的,生命周期与线程相同。虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执行的时候都会创建一个栈帧用于存储局部变量表,操作栈,动态链接,方法出口等信息。每一个方法被调用的过程就对应 一个栈帧在虚拟机栈中从入栈到出栈的过程。

精选大厂java多线程面试题50题

Java多线程50题 1)什么是线程? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。程序员可以通过它进行多处理器编程,你可以使用多线程对运算密集型任务提速。比如,如果一个线程完成一个任务要100毫秒,那么用十个线程完成改任务只需10毫秒。 2)线程和进程有什么区别? 线程是进程的子集,一个进程可以有很多线程,每条线程并行执行不同的任务。不同的进程使用不同的内存空间,而所有的线程共享一片相同的内存空间。别把它和栈内存搞混,每个线程都拥有单独的栈内存用来存储本地数据。更多详细信息请点击这里。 3)如何在Java中实现线程? https://www.wendangku.net/doc/3d5266905.html,ng.Thread类的实例就是一个线程但是它需要调用https://www.wendangku.net/doc/3d5266905.html,ng.Runnable接口来执行,由于线程类本身就是调用的 Runnable接口所以你可以继承https://www.wendangku.net/doc/3d5266905.html,ng.Thread类或者直接调用Runnable接口来重写run()方法实现线程。 4)Thread类中的start()和run()方法有什么区别? 这个问题经常被问到,但还是能从此区分出面试者对Java线程模型的理解程度。start()方法被用来启动新创建的线程,而且start()内部调用了run()方法,这和直接调用run()方法的效果不一样。当你

调用run()方法的时候,只会是在原来的线程中调用,没有新的线程启动,start()方法才会启动新线程。 5)Java中Runnable和Callable有什么不同? Runnable和Callable都代表那些要在不同的线程中执行的任务。Runnable从JDK1.0开始就有了,Callable是在JDK1.5增加的。它们的主要区别是Callable的call()方法可以返回值和抛出异常,而Runnable的run()方法没有这些功能。Callable可以返回装载有计算结果的Future对象。 6)Java内存模型是什么? Java内存模型规定和指引Java程序在不同的内存架构、CPU 和操作系统间有确定性地行为。它在多线程的情况下尤其重要。 Java内存模型对一个线程所做的变动能被其它线程可见提供了保证,它们之间是先行发生关系。 ●线程内的代码能够按先后顺序执行,这被称为程序次序 规则。 ●对于同一个锁,一个解锁操作一定要发生在时间上后发 生的另一个锁定操作之前,也叫做管程锁定规则。 ●前一个对Volatile的写操作在后一个volatile的读操作之 前,也叫volatile变量规则。 ●一个线程内的任何操作必需在这个线程的start()调用之 后,也叫作线程启动规则。 ●一个线程的所有操作都会在线程终止之前,线程终止规

将php序列化到数据库的对象饭序列化成java对象

将php序列化到数据库的对象饭序列化成java对象 php的对象序列化到数据库中,形如 a:3:{i:0;i:1241;i:1;i:4;i:2;i:16;}但是java需要取出这样的对象,转换成java的对象/* PHPSerializer.java * * Author: Ma Bingyao * Copyright: https://www.wendangku.net/doc/3d5266905.html, * Version: 2.1 * LastModified: 2006-08-09 * This library is free. You can redistribute it and/or modify it. * https://www.wendangku.net/doc/3d5266905.html,/?p=202 */ package org.phprpc.util; import java.io.*; import java.util.*; import https://www.wendangku.net/doc/3d5266905.html,ng.reflect.*;

class UnSerializeResult { public Object value; public int hv; public UnSerializeResult() {} public UnSerializeResult(Object value, int hv) { this.value = value; this.hv = hv; } } public class PHPSerializer { private static Package[] __packages = Package.getPackages(); private static final byte __Quote = 34; private static final byte __0 = 48; private static final byte __1 = 49; private static final byte __Colon = 58; private static final byte __Semicolon = 59; private static final byte __C = 67; private static final byte __N = 78;

字节跳动面试经验分享(非常详细)

字节跳动面试官一招差点KO我,一共面试了3轮(5年经验),艰难拿下2-2职级offer! 前言 我从大学毕业开始做Android开发,现在已经五年时间了,现在在山东老家济南做Android开发。这三年里面,也只是一心在做Android开发,其他语言接触的并不多,了解点JS之类的。现在感觉Android开始不像以前那样好做了,也可能是现在年纪慢慢大了,要考虑的事情变多了的缘故吧。 不知道以后应该何去何从,总是感觉做Android或者说做程序员一直处在一种不稳定之中,在一些中小公司里面,可能工作一年两年就因为各种各样的原因而离职。马上就要结婚了,该买房了。济南的房价一直在涨,而自己的收入还是这么不温不火的,加上这不稳定的工作,让人对于前途实在是乐观不起来。 再加上今年的大环境非常差,互联网企业裁员的现象比往年更严重了,可今年刚好是我的第一个“五年计划”截止的时间点,说什么也不能够耽搁了,所以早早准备的跳槽也在疫情好转之后开始进行了。但是,不得不说,这次字节的面试真的太难为我了,可以说是和面试官大战了3个回合,不过好在最后给了offer。 我个人情况是5年Android开发经验,字节跳动定级2-2(年薪是50-100w左右含加班费和股票折现,不含车餐房补)的样子,我是拿到了年薪60w+,13薪。下面是我的面试经历,与学习经验分享,希望能带来一些不一样的启发和帮助。 我与字节跳动面试官“大战”3回合,胜! 我的学习经验 1—4年大学 ?Java

无论什么级别的Android从业者,Java作为Android开发基础语言。不管是工作还是面试中,Java都是必考题。如果不懂Java的话,薪酬会非常吃亏(美团尤为重视Java基础) 详细介绍了Java泛型、注解、并发编程、数据传输与序列化、高效IO、容器集合、反射与类加载以及JVM重点知识线程、内存模型、JVM运行时内存、垃圾回收与算法、Java中四种引用类型、GC 分代收集算法 VS 分区收集算法、GC 垃圾收集器、JAVA IO/NIO 、JVM 类加载机制的各大知识点。 ?筑基必备 Android架构师筑基包括哪些内容呢: 1.深入 Java 泛型. 2.解深入浅出 3.并发编程 4.数据传输与序列化 5.Java 虚拟机原理 6.反射与类加载 7.高效 IO 8.Kotlin项目实战 大学1-4年架构师筑基必备 ?学习笔记整理 架构师筑基必备目录 架构师筑基必备第一章

Java-Jackson反序列化漏洞及挖洞思路

源码分析Jackson反序列化漏洞 前言: 本次分析从Java序列化和反序列化源码开始分析,进一步分析Jackson源码,找出造成漏洞的原因,最后以Jackson2.9.2版本,JDK1.80_171,resin4.0.52,CVE-2020-10673为例复现漏洞。 一.JA V A反序列化原理 1.1 Class对象 每一个类都有一个Class对象,Class对象包含每一个类的运行时信息,每一个类都有一个Class对象,每编译一个类就产生一个Class对象,Class类没有公共的构造方法,Class对象是在类加载的时候由JVM以及通过调用类加载器中的DefineClass()方法自动构造的,因此不能显式地声明一个Class对象。在类加载阶段,类加载器首先检查这个类的Class对象是否已经被加载。如果尚未加载,默认的类加载器就会根据类的全限定名查找.class文件。一旦某个类的Class对象被载入内存,我们就可以它来创建这个类的所有对象以及获得这个类的运行时信息。 获得Class对象的方法: 1).Class.forName(“类的全名”);//com.xx.xx.xx 2).实例对象.getClass() 3).类名.class 1.2反射 JA V A反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

实现Java反射机制的类都位于https://www.wendangku.net/doc/3d5266905.html,ng.reflect包中: 1).Class类:代表一个类 2).Field类:代表类的成员变量(类的属性) 3).Method类:代表类的方法 4).Constructor类:代表类的构造方法 5).Array类:提供了动态创建数组,以及访问数组的元素的静态方法 简单反射调用代码 Class clz=this.getClass(); Object obj= clz.getMethod("方法名",Class对象序列).invoke(this,Object参数序列); 1.3 反序列化 Java 序列化是指把Java 对象转换为字节序列的过程便于保存在内存、文件、数据库中,ObjectOutputStream类的writeObject() 方法可以实现序列化。 Java 反序列化是指把字节序列恢复为Java 对象的过程,ObjectInputStream 类的readObject() 方法用于反序列化。 RMI:是Java 的一组拥护开发分布式应用程序的API,实现了不同操作系统之间程序的方法调用。值得注意的是,RMI 的传输100% 基于反序列化,Java RMI 的默认端口是1099 端口。 JMX:JMX 是一套标准的代理和服务,用户可以在任何Java 应用程序中使用这些代理和服务实现管理,中间件软件WebLogic 的管理页面就是基于JMX 开发的,而JBoss 则整个系统都基于JMX 构架。 只有实现了Serializable接口的类的对象才可以被序列化,Serializable 接口是启用其序列化功能的接口,实现java.io.Serializable 接口的类才是可序列化的,没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化。 readObject() 方法的作用正是从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回,readObject() 是可以重写的,可以定制反序列化的一些行为。 readObject()主要做的事情,其实就是读取正常应该被序列化的字段信息后,

java序列化原理与算法

Java序列化原理和算法 总结: java中序列化算法的顺序: 1、子类的类信息描述 2、子类的字段信息描述(如果遇到类对象的属性,暂时用string的指针表示) 3、父类的类信息描述 4、父类的字段信息描述 5、对父类的字段信息进行赋值 6、对子类的字段信息进行赋值 7、发现子类的字段为类对象时,描述该类对象,并查找该类对象的父类,以以上方式描述,然后赋值。 本文讲解了Java序列化的机制和原理。从文中你可以了解如何序列化一个对象,什么时候需要序列化以及Java序列化的算法。 有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍。 Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization 是一种将这些字节重建成一个对象的过程。Java序列化API提供一种处理对象序列化的标准机制。在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的。 序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。 这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。如何序列化一个对象 一个对象能够序列化的前提是实现Serializable接口,Serializable接口没有方法,更像是个标记。 有了这个标记的Class就能被序列化机制处理。 import java.io.Serializable; class TestSerial implements Serializable { public byte version = 100; public byte count = 0; } 然后我们写个程序将对象序列化并输出。ObjectOutputStream能把Object输出成Byte流。 我们将Byte流暂时存储到temp.out文件里。 public static void main(String args[]) throws IOException { FileOutputStream fos = new FileOutputStream("temp.out");

java初级面试题

JAVA相关基础知识 1.Finally,final,finalize Finally:释放资源(内存之外的,打开的文件、连接、屏幕上的图形,,) ①总会执行 ②非后台线程结束,后台线程被强关,不会执行finally ③当try和catch中有return时,finally在return之后执行,但是返回值不会改变(finally中不会改变已保存的返回结果) ④finally中最好不要包含return,否则程序会从finally中退出,返回值不是try或catch中保存的返回值。 final: 基本数据类型:不可更改 类:不可继承 对象:引用不可变,对象内容可变 finalze:回收前调用,不适合用来清理或释放资源。对象免死最后机会!保证会被调用,但不保证会执行完(在低优先级线程中执行) 2. 数据在各个网络层之间是怎么传输的? 数据在各层之间的单位都是不一样的, 在物理层数据的单位称为比特(bit);在数据链路层,数据的单位称为(frame);在网络层,数据的单位称为数据包(packet);传输层,数据的单位称为数据段(segment)。 3. Hashtable、HashMap Hashtable 与HashMap类似,但是主要有6点不同。 1.HashTable的方法是同步的,HashMap未经同步,如Vector和ArrayList一样。 2.HashTable不允许null,key和value都不可以,HashMap允许null值,key和value 都可以。HashMap允许key值只能由一个null

3.HashTable有一个contains(Object value)功能和containsValue(Object value)功能一样。 4.遍历的时候,HashTable使用Enumeration,HashMap使用Iterator。 5.HashTable中hash数组默认大小是11,增加的方式是old*2+1。HashMap中hash 数组的默认大小是16,而且一定是2的指数。 6.哈希值的使用不同,HashTable直接使用对象的hashCode。 Hashtable继承自Dictionary类,实现了Map接口。而HashMap是继承自AbstractMap,实现了Map接口。 4. GET,POST区别? 答:基础知识:Http的请求格式如下。 主要包含三个信息:1、请求的类型(GET或POST),2、要访问的资源(如\res\img\a.jif),3、Http版本(http/1.1)

用来说明服务器要使用的附加信息 这是Http的规定,必须空一行 [] 请求的内容数据 区别: 1、Get是从服务器端获取数据,Post则是向服务器端发送数据。 2、在客户端,Get方式通过URL提交数据,在URL地址栏可以看到请求消息,该消息被编码过;Post数据则是放在Html header内提交。

Java序列化的机制和原理

Java序列化的机制和原理 有关Java对象的序列化和反序列化也算是Java基础的一部分,下面对Java序列化的机制和原理进行一些介绍。 Java序列化算法透析 Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization 是一种将这些字节重建成一个对象的过程。Java序列化API提供一种处理对象序列化的标准机制。在这里你能学到如何序列化一个对象,什么时候需要序列化以及Java序列化的算法,我们用一个实例来示范序列化以后的字节是如何描述一个对象的信息的。 序列化的必要性 Java中,一切都是对象,在分布式环境中经常需要将Object从这一端网络或设备传递到另一端。这就需要有一种可以在两端传输数据的协议。Java序列化机制就是为了解决这个问题而产生。 如何序列化一个对象 一个对象能够序列化的前提是实现Serializable接口,Serializable接口没有方法,更像是个标记。有了这个标记的Class就能被序列化机制处理。 1.import java.io.Serializable; 2. 3.class TestSerial implements Serializable { 4. 5.public byte version = 100; 6. 7.public byte count = 0; 8. 9.} 然后我们写个程序将对象序列化并输出。ObjectOutputStream能把Object输出成Byte 流。我们将Byte流暂时存储到temp.out文件里。 1.public static void main(String args[]) throws IOException { 2. 3. FileOutputStream fos = new FileOutputStream("temp.out "); 4. 5. ObjectOutputStream oos = new ObjectOutputStream(fos); 6. 7. TestSerial ts = new TestSerial();

JAVA经典面试题:Java内存模型

JAVA经典面试题:Java内存模型 因为Java内存模型不仅是java重点要学习的技术知识,还是面试的时候经典面试题,希望引起同学们的重视,今天千锋小编就来分享一下java内存模型的相关技术知识。 不同的渠道,内存模型是不一样的,但是jvm的内存模型标准是一致的。其实java的多线程并发问题都会反映在java的内存模型上,所谓线程安全无非是要操控多个线程对某个资源的有序拜访或修改。总结java的内存模型,要解决两个首要的问题:可见性和有序性。 可见性:多个线程之间是不能相互传递数据通信的,它们之间的交流只能经过同享变量来进行。Java内存模型(JMM)规定了jvm有主内存,主内存是多个线程同享的。当new一个目标的时分,也是被分配在主内存中,每个线程都有自己的作业内存,作业内存存储了主存的某些目标的副本,当然线程的作业内存大小是有限制的。当线程操作某个目标时,履行次序如下: (1) 从主存仿制变量到当前作业内存(read and load) (2) 履行代码,改动同享变量值(use and assign) (3) 用作业内存数据改写主存相关内容(store and write)

当一个同享变量在多个线程的作业内存中都有副本时,如果一个线程修改了这个同享变量,那么其他线程应该可以看到这个被修改后的值,这就是多线程的可见性问题。 有序性:线程在引证变量时不能直接从主内存中引证,如果线程作业内存中没有该变量,则会从主内存中复制一个副本到作业内存中,完成后线程会引证该副本。当同一线程再度引证该字段时,有可能从头从主存中获取变量副本(read-load-use),也有可能直接引证本来的副本(use),也就是说read,load,use次序可以由JVM完成体系决议。 线程不能直接为主存中字段赋值,它会将值指定给作业内存中的变量副本(assign),完成后这个变量副本会同步到主存储区(store- write),至于何时同步往昔,依据JVM完成体系决议。有该字段,则会从主内存中将该字段赋值到作业内存中,这个进程为read-load,完成后线程会引证该变量副本。 知识就财富,这句话再IT行业显示的尤其现实残酷,懂就是懂,不懂就是不懂,所以各位同学,你的努力与否与你财富直接挂钩。一起加油吧!更多java 技术经典面试题欢迎关注千锋小编。

java序列化的作用

1、序列化是干什么的? 简单说就是为了保存在内存中的各种对象的状态(也就是实例变量,不是方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。 2、什么情况下需要序列化 a)当你想把的内存中的对象状态保存到一个文件中或者数据库中时候; b)当你想用套接字在网络上传送对象的时候; c)当你想通过RMI传输对象的时候; 3、当对一个对象实现序列化时,究竟发生了什么? 在没有序列化前,每个保存在堆(Heap)中的对象都有相应的状态(state),即实例变量(instance ariable)比如: java 代码 1.Foo myFoo = new Foo(); 2.myFoo .setWidth(37); 3.myFoo.setHeight(70); 当通过下面的代码序列化之后,MyFoo对象中的width和Height实例变量的值(3 7,70)都被保存到foo.ser文件中,这样以后又可以把它从文件中读出来,重新在堆中创建原来的对象。当然保存时候不仅仅是保存对象的实例变量的值,JVM还要保存一些小量信息,比如类的类型等以便恢复原来的对象。 java 代码 1.FileOutputStream fs = new FileOutputStream("foo.ser"); 2.ObjectOutputStream os = new ObjectOutputStream(fs); 3.os.writeObject(myFoo); 4、实现序列化(保存到一个文件)的步骤 a)Make a FileOutputStream

Java对象的序列化和反序列化实践

Java对象的序列化和反序列化实践 当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种类型的数据,都会以二进制序列的形式在网络上传送。发送方需要把这个Java对象转换为字节序列,才能在网络上传送;接收方则需要把字节序列再恢复为Java对象。 把Java对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为Java对象的过程称为对象的反序列化。 对象的序列化主要有两种用途: 1)把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中; 2)在网络上传送对象的字节序列。 一.JDK类库中的序列化API java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。 java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。、 只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以采用默认的序列化方式。 对象序列化包括如下步骤: 1)创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流; 2)通过对象输出流的writeObject()方法写对象。 对象反序列化的步骤如下: 1)创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;

杭研Java秋招面经——【网易 笔试面试精品资源】

一面 Java内存模型讲一下 GC算法,知道的都讲一下 HashMap,get,put实现 JsonWebToken具体实现流程(简历) Spring AOP如何实现,写一个 AOP功能的主要流程 数据库引擎用过哪些,它们的区别 设计大流量访问系统,要做节流控制(类似秒杀) Linux命令用过哪些 频繁 gc排查处理 内存过大排查的处理,用 jmap,jstack怎么做,不用又怎么做 MySQL主从复制场景问题(bin_log) 项目中技术上最大的成长,项目中的问题解决方案讲一下 二面 手撕算法:比如 123+234=357,对应两个链表 3->2->1,4->3->2(输

入),输出结果链表(7->5->3),写一个函数实现,输入为两个链表,输出为一个结果链表。(考虑极端情况和进位情况,花了很久写出来还是不完善) 输入网址到展现发生了什么,越详细越好(我考虑了 DNS轮询,负载均衡和 CDN以及状态码,然后就全讲) 负载均衡是怎么做的,CDN具体是怎么实现的 TCP三次握手四次挥手 cookie和 session的区别,多台服务器的情况呢 四次挥手时最后两者的状态,Client的 TIME_WAIT避免什么问题,没有它会怎么样 SSM和 Spring Boot的区别 MyBatis和 Hibernate区别

TCP流量控制和拥塞控制,具体在场景中是怎么起作用的 Java线程和 OS中的线程的关系,与内存对应关系,一个 JVM线程数的上限受哪些因素限制 HR 挨个讲讲项目 项目哪个对技术成长大,哪个对个人成长大 面了哪些公司,走到了什么流程 为什么选择网易 之后的学习规划 全程自己讲了很多 总监面 protocolbuf主要优势(性能、安全性、跨语言) Java本身序列化存在的问题(不知道) Java内存模型 网络 IO编程中的内存使用了 JMM哪部分

《JAVA面向对象编程》([PDF] 孙卫琴著)

《JAVA面向对象编程》[PDF] 孙卫琴著 【目录】 第1章面向对象开发方法概述 1 1.1 结构化的软件开发方法简介3 1.2 面向对象的软件开发方法简介5 1.2.1 对象模型6 1.2.2 UML:可视化建模语言6 1.2.3 Rational Rose:可视化建模工具7 1.3 面向对象开发中的核心思想和概念7 1.3.1 问题领域、对象、属性、状态、行为、方法、实现7 1.3.2 类、类型9 1.3.3 消息、服务10 1.3.4 接口11 1.3.5 封装、透明12 1.3.6 抽象16 1.3.7 继承、扩展、覆盖17 1.3.8 组合19 1.3.9 多态、动态绑定22 1.4 UML语言简介24 1.4.1 用例图24 1.4.2 类框图25 1.4.3 时序图26 1.4.4 协作图27 1.4.5 状态转换图27 1.4.6 组件图28 1.4.7 部署图29 1.5 类之间的关系29 1.5.1 关联(Association)29 1.5.2 依赖(Dependency)31 1.5.3 聚集(Aggregation)31 1.5.4 泛化(Generalization)32 1.5.5 实现(Realization)32 1.5.6 区分依赖、关联和聚集关系33 1.6 实现Panel系统35 1.6.1 扩展Panel系统37 1.6.2 用配置文件进一步提高Panel系统的可维护性39 1.6.3 运行Panel系统40 1.7 小结41 1.8 思考题42 第2章第一个Java应用43 2.1 创建Java源文件43 2.1.1 Java源文件结构44

java序列化对象的方法

java序列化对象的方法 我们为大家收集整理了关于java序列化对象,以方便大家参考。ObjectOutputStream ?类用来序列化一个对象,如下的SerializeDemo例子实例化了一个Employee对象,并将该对象序列化到一个文件中。 ?该程序执行后,就创建了一个名为employee.ser文件。该程序没有任何输出,但是你可以通过代码研读来理解程序的作用。 ?注意: ?当序列化一个对象到文件时,按照Java的标准约定是给文件一个.ser扩展名。 ?import java.io.*;public class SerializeDemo{ public static void main(String ?[] args) { Employee e = new Employee(); https://www.wendangku.net/doc/3d5266905.html, = “Reyan Ali”; e.address = “Phokka Kuan, Ambehta Peer”; e.SSN = 11122333; e.number = ?101; try { FileOutputStream fileOut = new ?FileOutputStream(“/tmp/employee.ser”); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(e); out.close(); ?fileOut.close(); System.out.printf(“Serialized data is saved in ?/tmp/employee.ser”); }catch(IOException i) { i.printStackTrace(); } }} ?希望大家学业有成,工作顺利 ?

相关文档