Java程序的运行机制是怎么样的?

Java程序的运行机制是怎么样的?,第1张

Java程序的运行机制悄帆可以分为以下几个步骤:启瞎雹

编写Java源代码:首先,程序员需要使用Java编程语言编写源代码。Java源代码是以.java为扩展名的文本文件,包含了Java程序的逻辑和功能。

编译Java源代码:Java源代码需要通过Java编译器进行编译,生成字节码文件。字节码文件是以.class为扩展名的二进制文件,包含了Java程序的指令、变量和方法。

解释执行字节码文件:Java虚拟机(JVM)负责解释执行字节码文件。JVM是一个虚拟的计算机,它模拟了实际计算机的硬件和 *** 作系统,能够运行字节码文件。

类加载:当Java程序被执行时,JVM会根据需要动态加载所需的类。Java类库和自定义类都会被加载到内存中。

执行Java程序:JVM会按照程序的逻辑和功能执行Java程序。程序员可以在程序中使用Java类库和自定义类提供的方法和变量。

垃圾回收:JVM还负责垃圾回收,它会自动回收不再使用的内存空间,防止程序出现内存泄漏等问题。

总的来说,Java程序的运行机制可以概括为:编写源代码 ->编译生成字节码文神枯件 ->解释执行字节码文件 ->加载所需类 ->执行Java程序 ->垃圾回收。

在高级用户界面开发中,只能使用功能键来控制Command按钮,这些都是一些固定的模式,例如手机显示两个Command的话,分别对应屏幕上的左右两个Command,不需要用户去处理键值,所以不存在移植的问题,在所有的手机上都是通用的。

但是在低级用户界面开发中,可以直接获得手机的键值(keyCode),因为不同的手机中按键的键值存在差别,所以就存在移植的问题了。

在手机键盘上,可以简单的分为功能键区域和数字键区域搏猜,功能键指手机上的左右软键,中间的导航键以及接听电话和挂机键等,数字键区域指手机键盘上的 0-9数字键以及*号和#号键。其中功能键的个数以及键值,不同的手机区别很大,而数字键的区域基哪型的按键个数,以及按键的键值都是一样的。

所以在游戏中为了使程序通用,一般都不直接使用键值来进行判断,而是用游戏动作(gameAction)来进行判别的:实现的代码如下:

//将keyCode转换为游戏动作

int action = getGameAction(keyCode)

其中,keyCode和游戏动作的对应关系如下:

Canvas.UP——数字键2和向上导航键

Canvas.DOWN——数字键8和向下导航键

Canvas.LEFT——数字键4和向左导航键

Canvas.RIGHT——数字键6和向右导航键

Canvas.FIRE——数字键5和确定导航键

Game_A、Game_B、Game_C、Game_D分别对应键盘上的1、3、7、9或者是7、9、*、#键。

经过上面的转换以后,代码实现就和手机键盘上的键值无关了。

另外,如果是Nokia系列的缓毕手机,还可以使用com.nokia.mid.ui.FullCanvas类里面的SOFTKEY1、SOFTKEY2来控制Nokia系列手机上的左右两个软键,做到这两个软键的处理通用。

Java是一种跨平台的、解释型语言。Java 源代码编译中间“字节码”存储于class文件中。Class文件是一种字节码形式的中间代码,该字节码中包括了很多源册纳代码的信息,例如变量名、方法名等。因此,Java中间代码的反编译就变得非常轻易。目前市场上有许多免费的、商用的反编译软件,都能够生成高质量的反编译后的源代码。所以,对开发人员来说,如何保护Java程序就变成了一个非常重要的挑战。本文首先讨论了保护Java程序的基本方法,然后对代码混淆问题进行深入研究,最后结合一个实际的应用程序,分析如何在实践中保护Java程序。

反编译成为保护Java程序的最大挑战通常C、C++等编程语言开发的程序都被编译成目标代码,这些目标代码都是本机器的二进制可执行代码。通常所有的源文件被编译、链接成一个可执行文件。在这些可执行文件中,编译器删除了程序中的变量名称、方法名称等信息,这些信息往往是由内存地址表示,例如假如需要使用一个变量,往往是通过这个变量的地址来访问的。因此,反编译这些本地的目标代码就是非常困难的。

Java语言的出现,使得反编译变得非常轻易而有效。原因如下:1.由于跨平台的需求,Java的指令集比较简单而通用,较轻易得出程序的语义信息;2.Java编译器将每一个类编译成一个单独的文件,这也简化了反编译的工作;3.Java 的Class文件中,仍然保留所有的方法名称、变量名称,并且通过这些名称来访问变量和方法,这些符号往往带有许多语义信息。由于Java程序自身的特点,对于不经过处理的Java程序反编译的效果非常好。

目前,市场上有许多Java的反编译工具,有免费的,也有商业使用的,还有的是开放源代码的。这些工具的反编译速度和效果都非常不错。好的反编译软件,能够反编译出非常接近源代码的程序。因此,通过反编译器,黑客能够对这些程序进行更改,或者复用其中的程序。因此,如何保护Java程序不被反编译,是非常重要的一个问题。

常用的保护技术由于Java字节码的抽象级别较高,因此它们较轻易被反编译。本节介绍了几种常用的方法,用于保护Java字节码不被反编译。通常,这些方法不能够绝对防止程序被反编译,而是加大反编译的难度而已,因为这些方法都有自己的使用环境和弱点。

隔离Java程序最简单的方法就是让用户不能够访问到Java Class程序,这种方法是最根本的方法,具体实现有多种方式。例如,开发人员可以将要害的Java Class放在服务器端,客户端通过访问服务器的相关接口来获得服务,而不是直接访问Class文件。这样黑客就没有办法反编译Class文件。目前,通过接口提供服务的标准和协议也越来越多,例如 HTTP、Web Service、RPC等。但是有很多应用都不适合这种保护方式,例如对于单机运行的程序就无法隔离Java程序。这种保护方式见图1所示。

图1隔型搜离Java程序示意图对Class文件进行加密为了防止Class文件被直接反编译,许多开发人员将一些要害的Class文件进行加密,例如对注册码、序列号治理相关的类等。在使用这些被加密的类之前,程序首先需要对这些类进行解密,而后再将这些类装载到JVM当中。这些类的解密可以由硬件完成,也可以使用软件完成。

在实现时,开发人员往往通过自定义ClassLoader类卜姿历来完成加密类的装载(注重由于安全性的原因,Applet不能够支持自定义的ClassLoader)。自定义的ClassLoader首先找到加密的类,而后进行解密,最后将解密后的类装载到JVM当中。在这种保护方式中,自定义的ClassLoader是非常要害的类。由于它本身不是被加密的,因此它可能成为黑客最先攻击的目标。假如相关的解密密钥和算法被攻克,那么被加密的类也很轻易被解密。这种保护方式示意图见图2。

图2 对Class文件进行加密示意图转换成本地代码将程序转换成本地代码也是一种防止反编译的有效方法。因为本地代码往往难以被反编译。开发人员可以选择将整个应用程序转换成本地代码,也可以选择要害模块转换。假如仅仅转换要害部分模块,Java程序在使用这些模块时,需要使用JNI技术进行调用。

当然,在使用这种技术保护Java程序的同时,也牺牲了Java的跨平台特性。对于不同的平台,我们需要维护不同版本的本地代码,这将加重软件支持和维护的工作。不过对于一些要害的模块,有时这种方案往往是必要的。

为了保证这些本地代码不被修改和替代,通常需要对这些代码进行数字签名。在使用这些本地代码之前,往往需要对这些本地代码进行认证,确保这些代码没有被黑客更改。假如签名检查通过,则调用相关JNI方法。这种保护方式示意图见图3。

代码混淆 图3 转换成本地代码示意图代码混淆是对Class文件进行重新组织和处理,使得处理后的代码与处理前代码完成相同的功能(语义)。但是混淆后的代码很难被反编译,即反编译后得出的代码是非常难懂、晦涩的,因此反编译人员很难得出程序的真正语义。从理论上来说,黑客假如有足够的时间,被混淆的代码仍然可能被破解,甚至目前有些人正在研制反混淆的工具。但是从实际情况来看,由于混淆技术的多元化发展,混淆理论的成熟,经过混淆的Java代码还是能够很好地防止反编译。下面我们会具体介绍混淆技术,因为混淆是一种保护Java程序的重要技术。图4是代码混淆的示意图。

图4 代码混淆示意图几种技术的总结以上几种技术都有不同的应用环境,各自都有自己的弱点,表1是相关特点的比较。

混淆技术介绍表1 不同保护技术比较表 到目前为止,对于Java程序的保护,混淆技术还是最基本的保护方法。Java混淆工具也非常多,包括商业的、免费的、开放源代码的。Sun公司也提供了自己的混淆工具。它们大多都是对Class文件进行混淆处理,也有少量工具首先对源代码进行处理,然后再对Class进行处理,这样加大了混淆处理的力度。目前,商业上比较成功的混淆工具包括JProof公司的1stBarrier系列、Eastridge公司的JShrink和

4thpass.com

的SourceGuard等。主要的混淆技术按照混淆目标可以进行如下分类,它们分别为符号混淆(Lexical Obfuscation)、数据混淆(Data Obfuscation)、控制混淆(Control Obfuscation)、预防性混淆(Prevent Transformation)。

符号混淆在Class中存在许多与程序执行本身无关的信息,例如方法名称、变量名称,这些符号的名称往往带有一定的含义。例如某个方法名为getKeyLength(),那么这个方法很可能就是用来返回Key的长度。符号混淆就是将这些信息打乱,把这些信息变成无任何意义的表示,例如将所有的变量从vairant_001开始编号;对于所有的方法从method_001开始编号。这将对反编译带来一定的困难。对于私有函数、局部变量,通常可以改变它们的符号,而不影响程序的运行。但是对于一些接口名称、公有函数、成员变量,假如有其它外部模块需要引用这些符号,我们往往需要保留这些名称,否则外部模块找不到这些名称的方法和变量。因此,多数的混淆工具对于符号混淆,都提供了丰富的选项,让用户选择是否、如何进行符号混淆。

数据混淆 图5 改变数据访问数据混淆是对程序使用的数据进行混淆。混淆的方法也有多种,主要可以分为改变数据存储及编码(Store and Encode Transform)、改变数据访问(Access Transform)。

改变数据存储和编码可以打乱程序使用的数据存储方式。例如将一个有10个成员的数组,拆开为10个变量,并且打乱这些变量的名字;将一个两维数组转化为一个一维数组等。对于一些复杂的数据结构,我们将打乱它的数据结构,例如用多个类代替一个复杂的类等。

另外一种方式是改变数据访问。例如访问数组的下标时,我们可以进行一定的计算,图5就是一个例子。

在实践混淆处理中,这两种方法通常是综合使用的,在打乱数据存储的同时,也打乱数据访问的方式。经过对数据混淆,程序的语义变得复杂了,这样增大了反编译的难度。

控制混淆控制混淆就是对程序的控制流进行混淆,使得程序的控制流更加难以反编译,通常控制流的改变需要增加一些额外的计算和控制流,因此在性能上会给程序带来一定的负面影响。有时,需要在程序的性能和混淆程度之间进行权衡。控制混淆的技术最为复杂,技巧也最多。这些技术可以分为如下几类:增加混淆控制 通过增加额外的、复杂的控制流,可以将程序原来的语义隐藏起来。例如,对于按次序执行的两个语句A、B,我们可以增加一个控制条件,以决定B的执行。通过这种方式加大反汇编的难度。但是所有的干扰控制都不应该影响B的执行。图6就给出三种方式,为这个例子增加混淆控制。

图6 增加混淆控制的三种方式控制流重组 重组控制流也是重要的混淆方法。例如,程序调用一个方法,在混淆后,可以将该方法代码嵌入到调用程序当中。反过来,程


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12538272.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-26
下一篇 2023-05-26

发表评论

登录后才能评论

评论列表(0条)

保存