`
水上风荷
  • 浏览: 9051 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类

《深入Java虚拟机》学习笔记三:安全性(上)

    博客分类:
  • Java
阅读更多

第三章 安全性
1、为什么需要安全性
      因为Java是为网络而生,而网络提供了一条攻入连入网络计算机的潜在途径,因为安全性非常重要。
2、基本沙箱
      组成Java沙箱的基本组件如下:
            类装载器结构
            Class文件检查器
            内置于Java虚拟机(及语言)的安全性
            安全管理器及JavaAPI。 
      Java的沙箱安全模型,最重要的优点之一就是这些组件中的类装载器和安全管理器是可以由用户定制的。
3、类装载器体系结构
      在Java沙箱中,类装载器体系结构式第一道防线,毕竟是由类装载器将代码装入java虚拟机中的。它起的作用如下:
      1) 它防止恶意代码区干涉善意的代码。
      2) 它守护了被信任的类库边界。 
      3) 它将代码归入某类(称为保护域),该类确定了代码可以进行哪些操作。
      类装载器体系结构可以防止恶意代码区干涉善意代码,是通过为不同的类装载器装入的类提供不同的命名空间来实现的。命名空间是由一系列唯一的名称组成,每一个被装载的类有一个名字,这个命名空间是由Java虚拟机为每一个类装载器维护的。命名空间有助于安全的实现,因为你可以有效地在装入了不同的命名空间的类之间设置一个防护罩。在Java虚拟机中,在同一个命名空间内的类可以直接进行交互,而不同的命名空间中的类甚至不能察觉彼此的存在,除非显示的提供了允许它们进行交互的机制。
      类装载器体系结构守护了被信任的类库边界,是通过分别使用不同的类装载器装载可靠的包河不可靠的包来实现的。虽然通过赋给成员受保护(或包访问)的访问限制,可以在同一个包中的类型间授予彼此访问的特殊权限,但是这种特殊的权限只能授给在同一个包中的运行时成员,而且它们必须是由同一个类装载器封装的。
      用户自定义类装载器经常依赖其他类装载器,至少依赖于虚拟机启动时创建的启动类装载器来帮助它实现一些类装载请求。 在版本1.2之前,非启动类装载器必须显式地求助于其他类装载器,类装载器可以请求另一个用户自定义的类装载器来装载一个类,这个请求是通过对被请求的用户自定义类装载器调用loadClass()来实现的。除此以外,类装载器也可以通过调用findSystemClass()来请求启动类装载器来装载类,这是ClassLoader中的一个静态方法。 
      从版本1.2之后,类装载器请求另一个类装载器来装载类型的过程被形式化,称为双亲委派模式除启动类装载器之外的每一个类装载器,都一个“双亲”类装载器,在某一个特定的类装载器试图以常用的方式装载类型以前,它会先默认的将这个任务委派给他的双亲,请求他的双亲来装载这个类型。然后这个双亲依次请求他自己的双亲来装载这个类型,这个委派的过程一直向上继续,直到达到启动类装载器,通常启动类装载器是委派链中的最后一个雷装载器,如果一个雷装载器的双亲类装载器有能力来装载这个类型,则这个类型装载器返回这个类型。否则,这个类装载器试图自己来装载这个类型。
      在版本1.2之前的大多数虚拟机实现中,内置类装载器(原始类装载器)负责在本地装载可用的class文件。这些class文件通常包括哪些要运行的Java应用程序的class文件,以及这个应用程序所需的任何类库,这些类库中包含JavaAPI的基本class文件。从版本1.2以后,装载本地可以class文件的工作被分配到多个类装载器中,刚才称为原始类装载器的内置类装载器被重新命名为启动类装载器,表示它现在只负责装载哪些核心JavaAPI class文件,因为核心JavaAPI的class文件是用于启动Java虚拟机的class文件,所以启动类装载器也因此得名。
      从版本1.2之后,由用户自定义类装载器来负责其他class文件的封装。当Java虚拟机开始运行时,在应用程序启动之前,它至少创建一个用户自定义类装载器,也肯能创建多个。所有这些类装载器被链接在一个双亲-孩子的关系链中,在这条链的顶端是启动类装载器,在这条链的末端是一个被称为“系统类装载器”的类装载器。系统类装载器是指由Java应用程序创建的,新的用户自定义类装载器的默认委派双亲,这个默认的委派双亲通常是一个用户自定义类装载器(被称为用户自定义的类装载器,和启动类装载器相对而言,实际上有Java虚拟机实现提供)。
      如何使用类装载器来保护可信任类库?类装载器体系结构是通过剔除装作被信任的不可靠类,来保护可信任类库的边界的。在有双亲委派模式的情况下,启动类装载器可以抢在标准扩展类装载器之前图装载类,而标准扩展类装载器可以抢在路径类装载器之前去装载那个类,类路径类装载器又可以抢在网络类装载器之前去装载它。这样,在使用双亲-孩子委派链的方法中,启动类装载器会在最可信的类库—核心JavaAPI中首先检查每个被装载的类型,然后才依次到标准扩展,类路劲上的本地文件中检查。
      运行时包是在Java虚拟机第二版的规范中第一次出现的,它指由同一个类装载器装载的。属于同一个包的,多个类型的集合。在允许两个类型之间对包内可见的成员进行访问前,虚拟机不但要确定这两个类型属于同一个包,还必须确认它们属于同一个运行时包—它们必须是由同一个类装载器装载的。之所以提出运行时包的概念,动机之一是使用不同的类装载器装载不同的类。
      类装载器可以用另一种方法来保护被信任的类库的边界,,它只需要通过简单地拒绝装载特定的禁止类型就可以了。
4、class文件检查器
      和类装载器一起,class文件检验器保证装载的class文件内容有正确的内部结构,并且这些class文件相互协调一致。如果class文件检验器在class发现了问题,将抛出异样。
      Class文件检查器实现的安全目标之一就是程序的健壮性。Java虚拟机的Class文件检验器在字节码执行之前,必须完成大部分检查工作。他只在执行前而不是在执行中对字节码进行一次分析(并检验它的完整性),每一次遇到一个跳转指令时都进行检验。作为字节码确认工作的一部分,虚拟机将确认所有的跳转指令会到达另一条合法的指令,而且这条指令是在这个方法的字节流中的。
     Class文件检验器要进行四趟独立的扫描来完成他的操作:
     1)第一趟扫描,对每一段将被作为类型导入的字节序列,class文件检查器都会确认它是否符合Java class文件的基本结构。 在这次扫描中,检验器将进行许多检查:以魔数0XCAFEBABE开头?确定class文件中声明的主版本号和次版本号,这个版本号必须在这个Java虚拟机实现的可支持范围之内。确定这个class文件没有被删节,尾部也没有附带其他字节。
第一趟扫描的主要目的就是保证这个字节序列正确的定义了一个新的类型,它必须遵从Java的class文件固有格式,这样才能被编译成方法中的内部数据结构。第二、第三和第四趟扫描不是在符合class文件格式的二进制数据上进行的,而是在方法区中的,由实现决定的数据结构上进行的。 
     2)第二趟:类型数据的语义检查。在第二趟扫描中,class文件检查器进行的检查不需要查看字节码,也不需要查看和装载任何其他类型:在这趟扫描中,检验器查看每个组成部分,确认它们是否是其所属类型的实例,它们的结构是否正确。检验器对每个组成部分进行检查的目的之一是,为了确认每个方法描述都是符合特定语法的、格式正确的字符串。另外,class文件检验器检查这个类本身是否符合特定的条件,它们是由Java编程语言规定的。 
     3) 第三趟:字节码验证。在class文件检验器成功地进行了两趟检查后,它将注意力放在字节码上,这一趟扫描被称为“字节码验证“。在这趟扫描中,Java虚拟机对字节流进行数据流分析,这些字节流代表的是类的方法。
     字节码流代表了Java的方法,它是由被称为操作码的单字节指令组成的序列,每一个操作码后都跟着一个或多个操作数。操作数用于在Java虚拟机执行操作码指令时提供的额外的数据。执行字节码时,依次执行每个操作码,这就在Java虚拟机内构成了执行的线程。每一个线程被授予自己的Java栈,这个栈是由不同的栈帧构成的,每一个方法调用将获得一个自己的栈帧,栈帧其实就是一个内存片段,其中存储着局部变量和计算的中间结果。在栈帧中用于存储方法的中间结果的部分被称为该方法的操作数栈。操作码和它的(可选的)操作数可能指存储在操作数栈中的数据,或存储在方法栈帧中的局部变量中的数据。 这样,在执行一个操作码时,除了可以使用紧随其后的操作数,虚拟机还可以使用操作数栈中的数据,或局部变量中的数据,或者两者都用。
      字节码检查器要进行大量的检查,以确保采用任何路径在字节码流中都得到一个确定的操作码,确保操作数栈总是包含正确的数值以及正确的类型。它必须保证局部变量在赋予合适的值以前都不能被访问,而且类的字段中必须总是被赋予正确类型的值,类的方法被调用时总是传递正确的数值和类型的参数。字节码还必须保证每个操作码都是合法的,即每一个操作码都有合法的操作数,以及对每一个操作码,合适类型的数值位于局部变量中或是在操作数栈中。这些仅仅是字节码检验器所做的大量检查工作中的一个小部分,在整个检验过程中,它就能保证这个字节码流可以Java虚拟机安全的执行。
      字节码检验器并不试图检测出所有的安全问题。因为会遭遇“停机问题”,停机问题是计算机科学领域的一个著名论题:即不肯能写出一个程序,用它来判断作为其输入而读入的某个程序在执行时是否停机。
      字节码检验器处理停机问题的方法是,不去试图精确地让每个安全的程序都通过检查,虽然不能写出一个程序来判定任何给定程序是否会停机,但是可以写出一个简单的程序,让它只是识别出某些一定会停机的程序。Java字节码检验器就是这么做的,这个检验器检查确认读入的每一个字节码集合是否符合一个特定的规则集合。如果一个字节码集合能够遵从所有这些规则,那么检验器就知道它可以被虚拟机安全地执行。这样,通过识别一些安全的字节码流,但不是全部,检验器就绕过了停机问题。
      在第一、第二、第三趟扫描中,class文件检验器可以保证导入的class文件构成合理,内在一致,符合Java编程语言的限制条件,并且包含的字节码可以被Java虚拟机安全地执行。
      4) 第四趟:符号引用的验证。在动态链接的过程中,如果包含在一个class文件中的符号引用被解析时,class文件检验器将进行第四趟检查。在这趟检查中,Java虚拟机将追踪那些引用,从被验证的class文件到被引用的class文件,以确保这个引用是正确的。因为第四趟扫描必须检查被检测的class文件以外的其他类,所以这次扫描可能需要装载新的类。大多数Java虚拟机的实现采用延迟装载类的策略,直到类真正地被程序使用时才装载。即使一个实现确实需要预先装载了这些类,这是为了加快装载过程的速度,那它还是会表现为延迟装载。
       如果Java虚拟机在预先装载中发现它不能找到某个特定的被引用类,它并不在当时抛出NoClassDefFoundError错误,而是直到(或者除非)这个被引用的类首次被运行程序使用时才抛出。这样,如果Java虚拟机进行预先链接,第四趟扫描可以紧随第三趟扫描发生。但是如果Java虚拟机在某个符号引用第一次被使用时才进行解析,那么第四趟扫描将在第三趟以后很久,当字节码被执行时才进行。
      Class文件检验器的第四趟扫描仅仅是动态链接过程的一部分,当一个class文件被装载时,它包含了对其他类的符号引用以及它们的字段和方法。一个符号引用是一个字符串,它给出了名字,并且可能还包含了其他关于这个被引用项的信息,这些信息必须足以惟一地标识一个类,字段或方法。这样,对于其他类的符号引用必须给出这个类的全名,对于其他类的字段符号引用,必须给出类名、字段名以及字段描述符。对于其他类中的方法的引用必须给出类名、方法名以及方法的描述符。
       动态链接是一个将符号引用解析为直接引用的过程。当Java虚拟机执行字节码时,如果它遇到一个操作码,这个操作码第一次使用一个指向另一个类的符号引用,那么虚拟机必须解析这个符号引用,在解析时,虚拟机执行两个基本任务:一个是查找被引用的类,另一个是将符号引用替换为直接引用。 
      5) 二进制兼容
     因为Java程序是动态连接的,所以class文件检查器在第四次扫描中,必须检查相互引用的类之间是否兼容。

 

分享到:
评论
6 楼 水上风荷 2010-01-26  
快乐柠檬 写道
     

你很暴力呀!
5 楼 快乐柠檬 2010-01-21  
       
4 楼 快乐柠檬 2010-01-21  
    
3 楼 快乐柠檬 2010-01-21  
  
2 楼 快乐柠檬 2010-01-21  
   
1 楼 快乐柠檬 2010-01-21  
     

相关推荐

    深入理解Java虚拟机读书笔记之:第3章 安全(3)

    通过阅读《深入理解Java虚拟机》第三章,开发者不仅可以深入理解Java的安全机制,还能学习到如何在实际项目中实施这些安全策略,提升应用的安全性。对于想要从事Java开发或者对系统安全有深入了解需求的人来说,这一...

    深入理解Java虚拟机读书笔记之:第3章 安全(2)

    《深入理解Java虚拟机》是Java开发者必备的经典书籍之一,其第三章主要探讨了Java安全方面的内容。在Java中,安全是一个至关重要的主题,因为Java的设计目标之一就是提供一种可以在不同环境中安全运行的代码机制。本...

    Java 虚拟机学习笔记:Java 内存区域,垃圾收集,内存分配与回收策略,JVM 调优,文件结构,类加载机制,Java 程序

    Java 虚拟机学习笔记: Java 内存区域, 垃圾收集, 内存分配与回收策略, JVM 调优, 文件结构, 类加载机制, Java 程序 Java是一种面向对象的编程语言,由Sun Microsystems于1995年推出。它是一种跨平台的语言,...

    深入Java虚拟机JVM类加载学习笔记

    ### 深入Java虚拟机JVM类加载学习笔记 #### 一、Classloader机制解析 在Java虚拟机(JVM)中,类加载器(ClassLoader)是负责将类的`.class`文件加载到内存中的重要组件。理解类加载器的工作原理对于深入掌握JVM以及...

    学习笔记之java虚拟机

    ### 学习笔记之Java虚拟机详解 #### 运行时数据区域概览 Java虚拟机(JVM)运行时数据区域主要包括以下几部分:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区以及运行时常量池。 1. **程序计数器**: -...

    JVM:深入理解Java虚拟机 - 学习笔记

    《JVM:深入理解Java虚拟机》是一本深入解析Java虚拟机工作原理和技术细节的经典书籍。这份学习笔记将涵盖JVM的关键概念、架构以及它如何影响Java程序的性能。我们将探讨以下几个方面: 1. **JVM概述** Java虚拟机...

    java学习笔记markdown

    9. **JVM内部机制**:简述Java虚拟机的工作原理,包括类加载、内存管理、垃圾回收机制,有助于优化代码性能。 10. **泛型**:讨论Java泛型的使用,如何编写类型安全的代码,并理解其类型擦除的原理。 11. **枚举与...

    JVM 学习笔记(Java虚拟机)

    **JVM学习笔记(Java虚拟机)** Java虚拟机(JVM)是Java语言的核心组成部分,它是Java程序运行的平台,负责解释和执行字节码。深入理解JVM对于优化Java应用程序性能至关重要。本笔记将从以下几个方面详细介绍JVM:...

    java学习笔记资源合集

    Java 的三种核心机制为虚拟机机制、代码安全机制、垃圾回收机制。 Java 最大的特点是平台无关性(可移植性好),通过不同的虚拟机与各类操作系统无缝 结合。虚拟机实例是指:执行一个应用程序的时候,虚拟机产生一个...

    Java学习笔记(必看经典).doc

    它的设计目标是具有简单性、面向对象、健壮性、安全性、可移植性、高性能和多线程等特性。这份“Java学习笔记(必看经典).doc”文档将涵盖Java的核心概念和重要知识点,对于初学者和有经验的开发者来说都是宝贵的参考...

    尚硅谷JAVA基础笔记吐血整理

    它的设计目标是实现“一次编写,到处运行”,通过Java虚拟机(JVM)确保代码在不同操作系统上都能运行。Java语言的特点包括简洁性、面向对象、健壮性、安全性、高效性和可移植性。 【基本语法】 Java的基本语法包括...

    瑜琅java学习笔记

    以下是对该学习笔记各部分的深入解析: #### 1. Java起源 ##### 1.1 发展背景 - Java的诞生源于Sun Microsystems的一个项目,目标是开发一种新的编程语言和技术平台,以满足嵌入式系统和消费电子产品的需求。 - ...

    java基础学习笔记

    ### Java基础学习笔记知识点 #### 一、Java学习路线概览 Java学习通常分为几个阶段,从基础到高级,逐步深化。以下是对给定文件中提到的学习路线的详细解析: ##### 第一阶段:Java基础 - **JAVASE**:Java标准版...

    清华大学java学习笔记

    "清华大学java学习笔记" 本资源是一个详细的 Java学习笔记,由清华大学编写,涵盖了 Java 语言的概述、发展史、工作原理、特点等多方面的知识点。 Java 语言概述 Java 语言是一种面向对象的编程语言,具有安全、...

    Java 基础 第1阶段:基本语法-尚硅谷学习笔记(含面试题) 2023年

    Java是一种广泛使用的面向对象的编程语言,以其跨平台性、高效性和安全性著称。本学习资料专注于Java的基础语法,这是每个Java程序员必须掌握的核心知识。2023年的"Java 基础 第1阶段:基本语法——尚硅谷学习笔记...

    逐步深入的java学习笔记

    ### 逐步深入的Java学习笔记知识点总结 #### 一、Java环境配置 1. **JAVA_HOME**: 配置JDK的目录。这是Java环境的基本配置之一,用于指示系统JDK安装的位置。 - **Linux系统**: ```bash JAVA_HOME=/opt/jdk1.5.0...

    Java虚拟机JVM类加载学习笔记

    Java虚拟机(JVM)是Java程序的核心组成部分,它负责执行字节码并管理程序运行时的内存。本文主要探讨JVM的类加载机制,包括类加载、连接、初始化等关键过程,以及类的主动使用和被动使用的情况。 首先,我们要理解...

    java学习笔记总结.doc

    - **跨平台**:Java的“一次编写,到处运行”特性得益于其字节码和Java虚拟机(JVM),可以在任何支持JVM的平台上运行。 3. **IDE的使用**: 使用集成开发环境(IDE)如Eclipse,能提升开发效率。Eclipse可以帮助...

    java学习笔记整理

    【Java学习笔记整理】 Java是一种广泛使用的编程语言,它不仅是一种语言,还是一个软件开发平台和运行环境。Java分为三个主要版本:Java标准版(JSE)、Java缩微版(JME)和Java企业版(JEE)。JSE主要用于桌面应用...

Global site tag (gtag.js) - Google Analytics