动态链接库和共享目标库都是和具体的硬件平台相关的,当然不能通过与硬件平台无关的JAVA来链接了。DLL和SO都是通过目标文件链接才能得到了,JAVA可做不到这点。

解决方案 »

  1.   

    那看来java对付反编译真的是没什么招了如果不考虑平台无关,有没有办法呢????
      

  2.   

    to xiaohaiz(老土进城,两眼通红):
    愿闻其详
      

  3.   

    绕码器也可被称做“混淆器”-obfuscator
    混淆之后的字节码,并不改变执行的逻辑。但是可以提高反编译的难度。
    通常的混淆器做以下几件工作:
    (1) 将method内部的组织打乱;
    (2) 把java常量池内可以消除的SYMBOLIC DATA都消除;
    (3) 删除DEBUG信息;
    如果需要更大的强度,还需要在CLASS内部和CLASS之间做更多的混淆。但是混淆器并不是杜绝了被反编译的可能,只是增加其难度。只要反编译的开销大于反编译能够获取的利润,就达到了目的。
      

  4.   

    to xiaohaiz(老土进城,两眼通红):
    我已经试了JB自带的obfuscator了,感觉效果很差,根本起不了什么防反编译的功能。要是能做成so或dll,一来运行速度快了,二来反编译的难度也一定是大大增强了。JB自带有native编译器,不过只能编译成exe文件,好像没有找到编译成dll或so的选项。可惜了。
      

  5.   

    编译成为exe是可行的,机器码可以直接执行就可以了。
    而DLL和SO理论上就行不通,所以不用再试了。:)
      

  6.   

    to xiaohaiz(老土进城,两眼通红):
    要是在jsp中调用javabean,能不能在javabean中调用exe中的方法呢????
      

  7.   

    可以在javabean中调用exe执行。
    怎么可能调用exe中的方法呢!!??
    概念怎么回事?exe中还有方法这个概念吗?exe是执行的机器码啊!
      

  8.   

    to xiaohaiz(老土进城,两眼通红):
    机器码也有函数或方法的入口地址的吧???我就是奇怪为什么java可以生成exe机器码,不能生成dll机器码呢???
      

  9.   

    俺在LINUX下使用gcj可以把java编译到so。
    给你看看俺做的例子:
    1. A.java 和 B.java
       public class A {
           public void print() {System.out.println("Hello, A");}
       }
       public class B {
           public static void main(String[] args) {
               new A().println();
           }
       }
    2. 编译A.java 产生so
       gcj -shared A.java -o libA.so
    3. 编译B.java 并和libA.so链接 直接生成本地码
       gcj B.java --main=B -L. -lA
       生成a.out
    4. 运行a.out
       a.out, 输出:“Hello, A”
    ============================================
    5. 生成新的so,修改A的输出为“Hello!!!”
       gcj -shared A.java -o libA.so
    6. 再次运行a.out
       a.out,输出:“Hello!!!”
      

  10.   

    但是这样生成的so,是无法供java调用的,只能供java生成的本地代码(NATIVE CODE)调用。
      

  11.   

    如果在处理B.java的时候,不产生本地代码,而是产生class文件,由虚拟机解释执行,会得到类似这样的错误:
    不做:gcj --main=B B.java -L. -lA
    而做:gcj -C B.java
    虚拟机解释执行: gij B
    得到错误:
    <<
    Exception in thread "main" java.lang.InternalError: unexpected exception during linking: java.lang.ClassNotFoundException: A
       at 0xb7280d03: java.lang.Throwable.Throwable(java.lang.String) (/usr/lib/./libgcj.so.3)
       at 0xb7273b7e: java.lang.Error.Error(java.lang.String) (/usr/lib/./libgcj.so.3)
       at 0xb72810e6: java.lang.VirtualMachineError.VirtualMachineError(java.lang.String) (/usr/lib/./libgcj.so.3)
       at 0xb727551e: java.lang.InternalError.InternalError(java.lang.String) (/usr/lib/./libgcj.so.3)
       at 0xb7272c72: java.lang.ClassLoader.resolveClass0(java.lang.Class) (/usr/lib/./libgcj.so.3)
       at 0xb725e3fc: java.lang.Class.initializeClass() (/usr/lib/./libgcj.so.3)
       at 0xb725cc94: java.lang.Class.forName(java.lang.String, boolean, java.lang.ClassLoader) (/usr/lib/./libgcj.so.3)
       at 0xb725cd2f: java.lang.Class.forName(java.lang.String) (/usr/lib/./libgcj.so.3)
       at 0xb72c4edd: gnu.gcj.runtime.FirstThread.run() (/usr/lib/./libgcj.so.3)
       at 0xb7267b4c: _Jv_ThreadRun(java.lang.Thread) (/usr/lib/./libgcj.so.3)
       at 0xb723482c: _Jv_RunMain(java.lang.Class, byte const, int, byte const, boolean) (/usr/lib/./libgcj.so.3)
       at 0x08048930: ?? (??:0)
       at 0xb6ed0748: __libc_start_main (/lib/tls/libc.so.6)
       at 0x080486e1: ?? (??:0)
    >>
      

  12.   

    to  xiaohaiz(老土进城,两眼通红):
    高,至少走近了一步,可以生成.so,我回家后试试看有没有办法实现在java中调用.so,而不是在Native Code中调用,非常感谢!!!
      

  13.   

    TO superrg(秀华):
    呵呵,真是够认真。不过俺还是那个结论,做不到的。除非你使用JNI。
    SO是有通过符号表来操作的,系统调用dlopen等。在JAVA中无法直接操作SO的符号表。上面给你举的例子是用的GCJ,一个GCC的AHEADER编译器,归根到底还是使用C++语言。
      

  14.   

    to  xiaohaiz(老土进城,两眼通红):
    要是能用JNI调用到也不失为一个好方法呀,一来提高了代码的运行速度,二来大大增加了反编译的难度。目前市面上的native 编译器还真不少,但我接触得不多。经过你的提示,我在网上找了些相关资料,但没有说明这个问题的解决方案,只能按上面说的自己偿试了,呵呵。。参考网址为:
    http://www.ociweb.com/jnb/jnbJan2003.html
    跟你说的情形差不多,谢谢!
      

  15.   

    TO superrg(秀华):
    呵呵,不用客气。你给的链接刚才俺看了一下,写得比较清楚了,作为参考不错。
    你需要考虑的是如果使用了JNI虽然可能在性能提升和知识产权保护方面得到利益,但是确牺牲了平台无关性。需要仔细权衡。
      

  16.   

    to xiaohaiz(老土进城,两眼通红):
    昨天晚上加班了,这几天忙得很,回家累得不行了,估计可能要到周末才试了。平台无关性这个其实可以在代码中实现,以下是我的方案,仅供参考:
    1.用gcj把核心代码编译生成.so与.dll文件;
    2.用jbuilder编译生成native executable文件,目前jni好像不用写扩展名,如果需要写,可以在程序中先检测平台,再loadlibrary(.so || .dll),目前我只考虑windows && linux两种平台的无关性,其它的平台不予考虑;
    3.如果.so 或 .dll在不需要头文件的性况下可供JNI调用,那么利用JNI技术可以实现除Applet以外的其它应用,扩展、发布、维护都将非常方便。再次谢谢你的参考意见,欢迎继续讨论!
    Thx.
      

  17.   

    呵呵,凡事总要自给试过才有深刻的体会.你还是自己先试试.俺预测: 如果不使用JNI的方法,而是直接把JAVA生成共享目标库或者动态链接库.这些被gcj生成的库根本无法被你使用jbuilder产生的NativeCode调用的.
    符号表根本就对不上.
    GCJ是一个"Ahead-of-time Compiler",是gcc的一个前端(和g77是类似的,注:Fortran语言).俺觉得GCJ实际上是把java映射成C++,再把C++生成so或者NativeCode这么实现的.就是类似于"预编译"的作用.所以俺认为你的方案还是行不通. :)不过你还是自己试试,也许俺错了.
      

  18.   

    to xiaohaiz(老土进城,两眼通红):
    果然跟你说的一样,我试了几个所谓的本地编译器,效果都不是很理想,以下是一篇本地编译与JVM的对比评论:
    http://www-900.ibm.com/developerworks/cn/java/j-native/index.shtml我再试试其它的办法,非常感谢!
      

  19.   

    TO superrg(秀华):
    给出链接的文章很详细了.
    GCJ的本地代码当然不是性能最好的.
    前天晚上,和一个朋友在茶馆用笔记本电脑测试虚拟机的性能.
    Dell C640 (P41.8G, 256M) OS: Fedora Core Release 1, Kernel:2.4.22-1.2115.nptl测试的虚拟机有:
    SUN HotSpot 1.4.2_03
    GCJ's gij 3.3.2
    BEA JRockit 1.4.2_03 (8.1)
    还有gcj的本地代码和直接使用C++编写的代码.正如网上查到的性能评测文章一样,在x86平台上,JRockit是性能最好的虚拟机.性能直逼C++本地代码.比HotSpot(Linux)性能高出2-3倍(2种测试:内存分配/浮点计算.垃圾收集),而gij的性能表现是最低的.gcj本地代码的性能不如Jrockit.BTW,俺们的测试是很片面的,随手写的一些测试代码.但是也可以试着管窥全豹.如果你使用X86平台,并且考虑性能优先,可以考虑采用JRockit.