- 浏览: 595194 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (213)
- jdk (40)
- J2EE (8)
- JavaScript (16)
- spring (1)
- 正则 (10)
- ORACLE (18)
- CSS (1)
- 生活学习 (14)
- XML (3)
- Linux (11)
- 项目架设 (12)
- Junit (1)
- Derby (3)
- JMX (5)
- 版本控制 (4)
- PowerDesigner (1)
- 加密解密 (1)
- android (4)
- Eclipse (4)
- Hibernate (6)
- Tomcat (4)
- JasperReport&iReport (1)
- SqlServer (6)
- C++ (3)
- 系统架构涉及名词解释 (5)
- Hadoop (8)
- windows (2)
- SOA (1)
- 有趣的Google (1)
- 编程语言 (0)
- 数据结构与算法 (1)
- nodejs (1)
- 一些测试整理备份在这里吧 (0)
- 性能 (3)
- Drill (5)
- 学习 (1)
最新评论
前阵子写了个组件然后发现类no signer certificates,那么我就看看咋加一个吧,加之前说下JVM机制
JVM在执行字节码的时候需要经过下边的步骤:
由类加载器(Class Loader)负责把类文件加载到Java虚拟机中(.class),在这个过程需要校验该类文件是否符合类文件规范 。字节码校验器(Bytecode Verifier)检查该类文件的代码中是否存在着某些非法操作 ,如果字节码校验器校验通过,就由Java解释器负责把该类文件解释成机器码进行执行 。
JVM在上边操作过程使用了“沙箱”模型,即把Java程序的代码和数据都限制起来放在一定的内存空间执行,不允许程序访问该内存空间以外的内存。这种访问过程不仅仅是本地的,也可以是远程的,最明显的体验是使用RMI的时候。
一:“双亲委派类加载模型”:
双亲委派方式,指的是优先从顶层启动类加载器,自定向下的方式加载类模型,这种方式在“沙箱”安全模型里面做了第一道安全保障;而且这样的方式使得底层的类加载器加载的类和顶层的类加载器的类不能相互调用,哪怕两种类加载器加载的是同一个包里面的类,只要加载的时候不属于同一个类加载器,就是相互隔绝的,这样的操作称为JVM的“安全隔离”。
二:字节码校验:
字节码校验过程需要经过四个步骤:
检查class文件的内部结构是否正确,主要是检查该文件是否以某个内存地址打头一般为0xCAFEBABE,但是可能32bit和64bit存在一定的差异,通过这样的检查可以使得被损坏的class文件或者伪装的class文件不能够被加载,可以标记为不安全的。第一趟扫描的主要目的是保证这个字节序列正确的定义了一个类型,它必须遵从java class文件的固定格式,这样它才能被编译成在方法区中的(基于实现的)内部数据结构。
检查是否符合JVM语言特性里面的编译规则,因为Java里面所有的Class都是从Object类继承过来的,一旦发现这种不安全的类存在,就直接抛异常。这次检查,class文件检验器不需要查看字节码,也不需要查看和装载任何其他类型。在这趟扫描中,检验器查看每个组成部分,确认它们是否是其所属类型的实例,它们结构是否正确。比如,方法描述符(它的返回类型,以及参数的类型和个数)在class文件中被存储为一个字符串,这个字符串必须符合特定的上下文无关文法。另外,还会检查这个类本身是否符合特定的条件,它们是由java编程语言规定的。比如,除Object外,所有类都必须要有一个超类,final的类不能被子类化,final方法也没有被覆盖,检查常量池中的条目是合法的,而且常量池的所有索引必须指向正确类型的常量池条目。
检查字节码是否导致JVM崩溃掉,这里存在一个JVM中断的问题,编程过程无法捕捉Error,同样的没有办法判断程序是否因为执行的class字节码中断或者崩溃。字节码流代表了java的方法,它是由被称为操作码的单字节指令组成的序列,每一个操作码后都跟着一个或多个操作数。执行字节码时,依次执行操作码,这就在java虚拟机内构成了执行的线程,每一个线程被授予自己的java栈,这个栈是由不同的栈帧构成的,每一个方法调用将获得一个自己的栈帧——栈帧其实就是一个内存片段,其中存储着局部变量和计算的中间结果,用于存储中间结果的部分被称为操作数栈。字节码检验器要进行大量的检查,以确保采用任何路径在字节码流中都得到一个确定的操作码,确保操作数栈总是包含正确的数值以及正确的类型。它必须保证局部变量在赋予合适的值以前不能被访问,而且类的字段中必须总是被赋予正确类型的值,类的方法被调用时总是传递正确数值和类型的参数。字节码检验器还必须保证每个操作码都是合法的,即都有合法的操作数,以及对每一个操作码,合适类型的数值位于局部变量中或是在操作数栈中。这些仅仅是字节码检验器所做的大量检验工作中的一小部分,在整个检验过程通过后,它就能保证这个字节码流可以被java虚拟机安全的执行。
检查符号引用验证,一个类文件,它会包含它引用的其他类的全名和描述符,并跟他们建立符号引用(一种虚拟的,非物理连接的方式)。当程序第一次执行到需要符号引用的位置时,JVM会检查这个符号链接的正确性,然后建立真正的物理引用(直接引用)。java虚拟机将追踪那些引用——从被验证的class文件到被引用的class文件,以确保这个引用是正确的。这次扫描可能要装载新的类。考虑到虚拟机实现上的差别,第四趟扫描可能紧随第三趟扫描发生,也有可能在第三趟扫描之后很久,当字节码被执行时才执行。动态连接是一个将符号引用解析为直接引用的过程。当java虚拟机执行字节码时,如果它遇到一个操作码,这个操作码第一次使用一个指向另一个类的符号引用,那么虚拟机就必须解析这个符号引用。在解析时,虚拟机执行两个基本任务:
——查找被引用的类(如果必要的话就装载它)
——将符号引用替换为直接引用,例如指向一个类、字段或方法的指针或偏移量
虚拟机必须记住这个直接引用,这样当它以后再次遇到同样的引用时,就可以直接使用,而不需要重新解析该符号引用了。
三:内置于JVM的安全特性:
在执行期,除了符号引用验证,JVM还会对一些内建的安全特性进行检查
类型安全的引用转化
结构化的内存访问(非指针算法)
GC
数组边界检查
空引用检查(NullPointer)
强制内存的结构话访问,避免了恶意用户在了解内存分布的情况下通过指针对JVM的内部结构进行破外。当然要了解JVM的内存分布也不是易事。JVM对运行时数据空间的分配是一个黑盒过程,完全由JVM自己决定如何分配,在class中没有任何相关的信息。
字节码检查的局限就是对于那些不经过字节码检查的方法(如本地方法:native method)无法验证其安全性,所以这里采用的是对动态链接库的访问控制,对于那些足有足够可信度的代码才被允许访问本地方法。具体的实现是,由安全管理器来决定代码是否有调用动态链接库的权限,因为调用本地方法必须调用动态链接库。这样一来,不可信的代码将无法通过调用本地方法来绕过字节码检查。
四:安全管理器SecurityManager: 这一步是编程中最接近程序的一个环节,SecurityManager存在于JavaAPI里面,是可以通过编程来完成安全策略管理的,默认情况下,Java应用是不设置SecurityManager实例的,但是这个实例却需要我们在启动的时候通过System.setSecurityManager来进行设置。一般情况下,调用了SecurityManager.checkPermission(Permission perm)来完成的,外部程序可以创建一个权限实例Permission来进行Check操作。主要应用为:
默认安全管理器:java.lang.SecurityManager
代码签名和认证
策略:java.security.Policy
权限:java.security.Permission
策略文件
保护域:CodeSource,PersimissionCollection,ProtectionDomain
访问控制器:java.security.AccessController
五:Java签名/证书机制:
Java签名机制使得使用者可以安全调用外部提供的jar文件,签名必须是基于jar包的,也就是如果要使用安全模型必须要将提供的class文件打包成jar,然后使用JDK工具(jarsigner)对jar进行签名。新安全平台中对足够信任度的代码放宽了限制,要获得充分信任须通过代码签名来实现,若我们对某一签名团体足够信任,比如SUN,那么具有该团体签名的代码将被给予充分信任。一个基本的思路大致为,代码发布者创建私钥/公钥对,然后利用私钥对发布代码进行签名,代码使用方在获得代码发布者提供的公钥后对代码进行验证,确认代码确为该提供者提供以及在发布后未经非法修改。这其中存在一些潜在的危险,既是公钥是否是该代码发布者提供的,恶意用户可能替换掉合法的公钥,这会导致用户将给与恶意用户发布的代码以充分信任,目前的常见做法是通过一些权威的证书机构来发布证书而不是公钥,代码发布者被证书发布机构认证合格后,可以将自己的公钥交付证书发布机构,证书发布机构再通过私钥加密该公钥,从而生成证书序列。这样替换公钥的可能性就变得微乎其微。不过世上无绝对安全之事,通过证书机构发布的证书也不是绝对安全的途径。
证书是在签名基础上,对签名值,再进一步做一次加密。而这次加密使用的私钥和公钥都是证书机构提供的。这种方式,是为了防止,有些恶意用户,在公钥发到你手上前,就对其做了手脚,然后再发一个动过手脚的jar给你,用动过手脚的公钥解动过手脚的jar包,是可以解开的。而使用证书后,它会对已经加密的签名值,再做一层加密,这样,到你手里,你只需要通过证书机构的公钥进行解密,然后再用jar包发布者的公钥解密就行了。
JVM在执行字节码的时候需要经过下边的步骤:
由类加载器(Class Loader)负责把类文件加载到Java虚拟机中(.class),在这个过程需要校验该类文件是否符合类文件规范 。字节码校验器(Bytecode Verifier)检查该类文件的代码中是否存在着某些非法操作 ,如果字节码校验器校验通过,就由Java解释器负责把该类文件解释成机器码进行执行 。
JVM在上边操作过程使用了“沙箱”模型,即把Java程序的代码和数据都限制起来放在一定的内存空间执行,不允许程序访问该内存空间以外的内存。这种访问过程不仅仅是本地的,也可以是远程的,最明显的体验是使用RMI的时候。
一:“双亲委派类加载模型”:
双亲委派方式,指的是优先从顶层启动类加载器,自定向下的方式加载类模型,这种方式在“沙箱”安全模型里面做了第一道安全保障;而且这样的方式使得底层的类加载器加载的类和顶层的类加载器的类不能相互调用,哪怕两种类加载器加载的是同一个包里面的类,只要加载的时候不属于同一个类加载器,就是相互隔绝的,这样的操作称为JVM的“安全隔离”。
二:字节码校验:
字节码校验过程需要经过四个步骤:
检查class文件的内部结构是否正确,主要是检查该文件是否以某个内存地址打头一般为0xCAFEBABE,但是可能32bit和64bit存在一定的差异,通过这样的检查可以使得被损坏的class文件或者伪装的class文件不能够被加载,可以标记为不安全的。第一趟扫描的主要目的是保证这个字节序列正确的定义了一个类型,它必须遵从java class文件的固定格式,这样它才能被编译成在方法区中的(基于实现的)内部数据结构。
检查是否符合JVM语言特性里面的编译规则,因为Java里面所有的Class都是从Object类继承过来的,一旦发现这种不安全的类存在,就直接抛异常。这次检查,class文件检验器不需要查看字节码,也不需要查看和装载任何其他类型。在这趟扫描中,检验器查看每个组成部分,确认它们是否是其所属类型的实例,它们结构是否正确。比如,方法描述符(它的返回类型,以及参数的类型和个数)在class文件中被存储为一个字符串,这个字符串必须符合特定的上下文无关文法。另外,还会检查这个类本身是否符合特定的条件,它们是由java编程语言规定的。比如,除Object外,所有类都必须要有一个超类,final的类不能被子类化,final方法也没有被覆盖,检查常量池中的条目是合法的,而且常量池的所有索引必须指向正确类型的常量池条目。
检查字节码是否导致JVM崩溃掉,这里存在一个JVM中断的问题,编程过程无法捕捉Error,同样的没有办法判断程序是否因为执行的class字节码中断或者崩溃。字节码流代表了java的方法,它是由被称为操作码的单字节指令组成的序列,每一个操作码后都跟着一个或多个操作数。执行字节码时,依次执行操作码,这就在java虚拟机内构成了执行的线程,每一个线程被授予自己的java栈,这个栈是由不同的栈帧构成的,每一个方法调用将获得一个自己的栈帧——栈帧其实就是一个内存片段,其中存储着局部变量和计算的中间结果,用于存储中间结果的部分被称为操作数栈。字节码检验器要进行大量的检查,以确保采用任何路径在字节码流中都得到一个确定的操作码,确保操作数栈总是包含正确的数值以及正确的类型。它必须保证局部变量在赋予合适的值以前不能被访问,而且类的字段中必须总是被赋予正确类型的值,类的方法被调用时总是传递正确数值和类型的参数。字节码检验器还必须保证每个操作码都是合法的,即都有合法的操作数,以及对每一个操作码,合适类型的数值位于局部变量中或是在操作数栈中。这些仅仅是字节码检验器所做的大量检验工作中的一小部分,在整个检验过程通过后,它就能保证这个字节码流可以被java虚拟机安全的执行。
检查符号引用验证,一个类文件,它会包含它引用的其他类的全名和描述符,并跟他们建立符号引用(一种虚拟的,非物理连接的方式)。当程序第一次执行到需要符号引用的位置时,JVM会检查这个符号链接的正确性,然后建立真正的物理引用(直接引用)。java虚拟机将追踪那些引用——从被验证的class文件到被引用的class文件,以确保这个引用是正确的。这次扫描可能要装载新的类。考虑到虚拟机实现上的差别,第四趟扫描可能紧随第三趟扫描发生,也有可能在第三趟扫描之后很久,当字节码被执行时才执行。动态连接是一个将符号引用解析为直接引用的过程。当java虚拟机执行字节码时,如果它遇到一个操作码,这个操作码第一次使用一个指向另一个类的符号引用,那么虚拟机就必须解析这个符号引用。在解析时,虚拟机执行两个基本任务:
——查找被引用的类(如果必要的话就装载它)
——将符号引用替换为直接引用,例如指向一个类、字段或方法的指针或偏移量
虚拟机必须记住这个直接引用,这样当它以后再次遇到同样的引用时,就可以直接使用,而不需要重新解析该符号引用了。
三:内置于JVM的安全特性:
在执行期,除了符号引用验证,JVM还会对一些内建的安全特性进行检查
类型安全的引用转化
结构化的内存访问(非指针算法)
GC
数组边界检查
空引用检查(NullPointer)
强制内存的结构话访问,避免了恶意用户在了解内存分布的情况下通过指针对JVM的内部结构进行破外。当然要了解JVM的内存分布也不是易事。JVM对运行时数据空间的分配是一个黑盒过程,完全由JVM自己决定如何分配,在class中没有任何相关的信息。
字节码检查的局限就是对于那些不经过字节码检查的方法(如本地方法:native method)无法验证其安全性,所以这里采用的是对动态链接库的访问控制,对于那些足有足够可信度的代码才被允许访问本地方法。具体的实现是,由安全管理器来决定代码是否有调用动态链接库的权限,因为调用本地方法必须调用动态链接库。这样一来,不可信的代码将无法通过调用本地方法来绕过字节码检查。
四:安全管理器SecurityManager: 这一步是编程中最接近程序的一个环节,SecurityManager存在于JavaAPI里面,是可以通过编程来完成安全策略管理的,默认情况下,Java应用是不设置SecurityManager实例的,但是这个实例却需要我们在启动的时候通过System.setSecurityManager来进行设置。一般情况下,调用了SecurityManager.checkPermission(Permission perm)来完成的,外部程序可以创建一个权限实例Permission来进行Check操作。主要应用为:
默认安全管理器:java.lang.SecurityManager
代码签名和认证
策略:java.security.Policy
权限:java.security.Permission
策略文件
保护域:CodeSource,PersimissionCollection,ProtectionDomain
访问控制器:java.security.AccessController
五:Java签名/证书机制:
Java签名机制使得使用者可以安全调用外部提供的jar文件,签名必须是基于jar包的,也就是如果要使用安全模型必须要将提供的class文件打包成jar,然后使用JDK工具(jarsigner)对jar进行签名。新安全平台中对足够信任度的代码放宽了限制,要获得充分信任须通过代码签名来实现,若我们对某一签名团体足够信任,比如SUN,那么具有该团体签名的代码将被给予充分信任。一个基本的思路大致为,代码发布者创建私钥/公钥对,然后利用私钥对发布代码进行签名,代码使用方在获得代码发布者提供的公钥后对代码进行验证,确认代码确为该提供者提供以及在发布后未经非法修改。这其中存在一些潜在的危险,既是公钥是否是该代码发布者提供的,恶意用户可能替换掉合法的公钥,这会导致用户将给与恶意用户发布的代码以充分信任,目前的常见做法是通过一些权威的证书机构来发布证书而不是公钥,代码发布者被证书发布机构认证合格后,可以将自己的公钥交付证书发布机构,证书发布机构再通过私钥加密该公钥,从而生成证书序列。这样替换公钥的可能性就变得微乎其微。不过世上无绝对安全之事,通过证书机构发布的证书也不是绝对安全的途径。
证书是在签名基础上,对签名值,再进一步做一次加密。而这次加密使用的私钥和公钥都是证书机构提供的。这种方式,是为了防止,有些恶意用户,在公钥发到你手上前,就对其做了手脚,然后再发一个动过手脚的jar给你,用动过手脚的公钥解动过手脚的jar包,是可以解开的。而使用证书后,它会对已经加密的签名值,再做一层加密,这样,到你手里,你只需要通过证书机构的公钥进行解密,然后再用jar包发布者的公钥解密就行了。
发表评论
-
关于饿汉式单例首次初始化失败后,可以再次尝试?
2012-07-11 15:14 1265思考一个问题,以下代码是一个简单的饿汉式单例代码,显然在第一次 ... -
由ApacheCommon-BeanUtils1.8.3发现的Java HotSpot(TM)的Bug
2012-07-03 15:42 1604由ApacheCommon-BeanUtils1.8.3发现的 ... -
JVM垃圾回收
2012-04-19 13:02 3523一、JVM内存模型及垃圾收集算法 1.根据Java虚 ... -
Java构建HashCode相同字符串算法
2012-01-10 15:05 5563import java.math.BigDecimal; ... -
线程全部结束与集合点
2011-11-12 16:26 1253final int size = 50; fin ... -
ddddddddd
2011-11-12 16:21 1256dddddddddd -
ccccccc
2011-11-12 16:20 1970ccccccccccc -
bbbbbb
2011-11-12 16:19 1764bbbbb -
Aaaaa
2011-11-12 16:19 928aaaaaaaa -
备忘链接
2011-08-16 18:25 954翻译,随便写了写,备忘一下 URLConnection co ... -
jvisualvm监听JVM
2011-08-05 10:14 1206配置好 set JAVA_OPTS=%JAVA_OPTS ... -
JVM 调优 技巧
2011-08-02 15:59 12581.升级 JVM 版本。如果能使用64-bit,使用64-bi ... -
JVM垃圾回收策略
2011-08-02 14:59 1062为什么要分代 分代的垃圾回收策略,是基于这样一个事实:不 ... -
Java GC
2011-08-02 13:38 1052调整JVM GC(Garbage Collection),可 ... -
Java的弱引用(Weak Reference)
2011-05-18 16:07 1250要理解弱引用,首先要 ... -
使用classloader动态加载Class
2011-05-17 14:25 965http://www.javaworld.com/javawo ... -
查看class文件信息
2011-05-16 14:15 1701看了第6章的java class文件这一部分,我觉得对clas ... -
.class文件格式--java字节码文件的格式
2011-05-14 23:07 25441 . 目的 Java 虚拟机识别的 class 文件格式包含 ... -
Calendar
2011-03-30 14:13 1054/**获得参数月份的一号及其下一个月的一号*/ priva ... -
Bad version number in .class file
2011-03-04 15:08 1338java.lang.UnsupportedClassVersi ...
相关推荐
4. 类加载器之间的委托机制确保了类加载的一致性和安全性。 #### 实验总结 通过本次实验,不仅加深了对JVM类加载机制的理解,还学会了如何利用类加载器和单例模式来优化程序结构和性能。在实验过程中遇到了一些小...
7. 安全管理:JVM执行严格的类型检查和权限控制,确保代码的安全性。 8. 调优工具:如JVisualVM、JConsole等,帮助开发者监控和调整JVM的性能。 了解JVM源码可以帮助我们深入理解Java程序的运行过程,优化内存使用...
Java虚拟机(JVM)的类...总结来说,JVM类加载机制保证了Java程序的稳定性和安全性,通过一系列步骤将类的定义转换为运行时可用的对象。了解这个机制对于优化代码性能、解决内存问题以及深入理解Java运行原理至关重要。
JVM的主要职责包括加载Java程序、验证字节码、将字节码转换成机器码执行、内存管理、垃圾回收和提供安全机制等。JVM的内存管理主要分为堆(Heap)、栈(Stack)、本地方法栈(Native Method Stack)、方法区(Method...
1. **类的加载机制**:这是JVM的基础,负责加载Java类,并准备执行这些类。类加载机制确保了类的正确加载,并管理类的生命周期。 2. **JVM内存结构**:主要包括堆、栈、方法区等,用于存储和管理数据。 3. **GC...
JVM通过执行时验证机制确保字节码的安全性,防止恶意代码的执行。 #### 另一个示例 假设我们有一个简单的Java程序,包含两个类`Main`和`Helper`。`Main`类中有一个`main`方法,该方法调用了`Helper`类的一个静态...
- **安全机制**:JVM 提供了沙箱安全模型,确保 Java 程序不会对操作系统造成破坏。 ### 3. Oracle JInitiator 版本背景 Oracle JInitiator 是一种用于在浏览器环境中运行 Java 应用程序的技术。它允许用户在没有...
本文将深入探讨“访问控制器的栈校验机制”,这是JVM安全模型的重要组成部分。 栈校验机制是JVM在执行字节码时进行的一种静态类型检查。当方法调用、字段访问或数组操作等指令被执行时,JVM会检查操作数栈中的数据...
6. 安全特性:JVM提供类级的安全机制,包括字节码验证器、类加载器的安全检查等,以防止恶意代码破坏JVM的安全性。 关于性能调优的最佳实践,首先需要进行性能分析,通过监控工具(如jvisualvm、jconsole等)来获取...
- **安全性**:字节码在执行前会经过JVM的安全检查,确保其不会对系统造成损害。 - **高效性**:虽然字节码的执行速度通常低于本地机器码,但在JVM的优化下,实际运行效率往往很高。 #### JVM的内存管理机制 JVM的...
基本类型在编译时进行类型检查,JVM的字节码指令根据操作数的类型进行相应操作。例如,iadd指令用于执行整数相加,而fadd指令则用于执行浮点数相加。对于boolean类型,虽然没有专门的指令,但通常使用integer指令...
使用JVisualVM、JConsole等工具监控JVM的运行状态,定期检查GC日志,分析对象的创建和销毁情况,从而找出性能瓶颈并针对性地进行优化。例如,JVisualVM提供了丰富的监控功能,可以帮助开发者深入了解JVM的内存使用...
2. **安全性**:JVM提供了严格的类型检查和安全限制,防止恶意代码破坏系统。 3. **动态性**:JVM允许程序在运行时动态加载类和资源,增强了软件的灵活性和可扩展性。 4. **内存管理**:自动的垃圾回收机制简化了...
类加载时,会先由父类加载器检查是否已加载,如果没有则向下传递。这样可以避免类的重复加载,并保证核心类库的安全。 9. **解释一下JNI(Java Native Interface)?** JNI是Java与本地代码交互的接口,允许Java...
这些参数通常以-XX:开头,允许开发者调整JVM内部的工作机制,以适应特定的应用场景和性能需求。以下是一些关键的JVM选项及其详细解释: 1. -XX:+<option> / -XX:-<option>: 这些选项用于启用或禁用某个特性。例如,...
加载过程确保类的安全性和正确性,验证阶段检查字节码是否符合规范,准备阶段为静态变量分配内存并设置默认值,解析阶段将符号引用转换为直接引用,初始化阶段执行类构造器`<clinit>`方法。 **2. 内存区域** JVM...
- **目标**:深入理解JVM的工作原理,掌握JIT编译器的机制及其对程序性能的影响。 - **内容**:涵盖JVM基础知识、JIT编译原理、字节码与机器码的区别等内容。 #### 三、JVM知识结构 - **知识结构**:包括基础概念...
3. **类型转换指令**:如`i2d`将整型值转换为双精度浮点数,`checkcast`用于类型检查,确保对象引用可以安全地转换为指定类型。 4. **控制流程指令**:如`if_icmpeq`比较两个栈顶的整数是否相等,`goto`无条件跳转...