刚买了一只加密狗,厂商接供了访问该狗的java类,该类使用了JNI接口,故无法改变该类的类名和包名。该类没有包名,即默认无包名的类,必须放到程序运行的根目录下。现在我使用JDK1.5,我所有的类若使用厂商提供的类访问狗,也必须不能带包名,即放到程序运行的根目录下,无法通过import导入没有包名的类。难道在JAVA中一个类若没有包名,就不能被有包名的类导入或使用吗?为了使用没有包名的类,必须我其它的类也不能有包名?不这样做就通不过编译,这是怎么回事?
注:厂商提供的无包名类为public类型。

解决方案 »

  1.   

    试过了,不行。设定了classpath和path都不行。上面这个问题没有人遇到过吗?
      

  2.   

    使用 import JavaClass;
    这样的语法根本通不过编译。
    不使用import的话就必须放到跟JavaClass类同样的根目录下,变成无名包的类。
    所有可能的方法我都试过了。
      

  3.   

    我也试过了,这的确是个问题。这样算得上是使用到了:
    Class.forName("NoPackage").newInstance();不过这样也很麻烦的
    这个厂商也太不地道了,连个包名都没有,何况包名还可以顺便给他自己打广告。你应该找厂商更改,否则你就退货。你也可以全部翻编译,然后移动到一个包下面去。
      

  4.   

    要求厂商重编译代码
    import *.class太麻烦
      

  5.   

    up! tomcat5也是有这毛病,要想引入javabean,必须编译的类要有包名
      

  6.   

    因为有JNI调用,所以厂商的类不能改写。虽然厂商的类可以继承,但继承时也不能加包名,否则也无法通过编译。这意味我的程序只要有一处使用了厂商的类,所有其它的类都不能带包名,直郁闷,哪位高手知道解决办法?
      

  7.   

    只有JAVA反射机制可以解决此问题,但这样使用类实在太不方便了。
    厂商说我如果订购500个以加密狗上的话,可以经我重新编译一个类,加上包名。太不象话了
      

  8.   

    只有JAVA反射机制可以解决此问题,但这样使用类实在太不方便了。
    厂商说我如果订购500个以上加密狗上的话,可以给我重新编译一个类,加上包名。
    退货,又花钱又麻费,没准还退不掉,怎么也是我赔本买卖。
      

  9.   

    他的JAVA类提供了源代码,但是相关的JNI调用使用的DLL库没有源代码,反编译重写一遍根本不现实。
      

  10.   

    其实不是这样的,就算一个类没有包名,它还是可以被访问到,只要它可以被编译器找到。而且你的类还是public的,就更好说了。难道在JAVA中一个类若没有包名,就不能被有包名的类导入或使用吗?为了使用没有包名的类,必须我其它的类也不能有包名?如果你的类A是package包,而你的类B是默认包的(就是没有包名的),那你就不能通过import包名来用你的类B,但是因为你的B是默认包的,所有你就把把它放到默认包中就可以了,编译器就会找到,因为,如果你的文件没有通过import导入包,编译器就会在默认包中寻找你需要的类。呵呵,到这里你知道其实你不用必须把你的类B和A放到同一个文件夹啦。默认包的位置就是你的classpath的位置。
    如果你想把类B放在C:/dog这个文件夹中,类A不在C:/dog中,也想顺利访问到类B,那么你就把C:/dog放到你的classpath中,这样C:/dog就会成为默认包的位置了。
      

  11.   

    可以不可以把这个类添加到jar中去了?
      

  12.   

    你有他的源代码? 那就好办了。方法就是把他的类中你要用到的方法抽出来自己写一个接口,然后修改他的类实现这个接口,你的程序中只通过接口来访问。就像下面这样://Dog.java
    public class Dog implements yourpackage.IDog {
    public void method1() {
    ...
    } public int method2() {
    ...
    return xxx;
    } ...
    }
    //IDog.java
    package yourpackage;public class interface IDog {
    public void method1();
    public int method2();
    ...
    }
    //DogFactory.java
    package yourpackage;public class DogFactory {
    private static IDog dog = null; public static IDog createDog() {
    if (dog == null) {
    try {
    dog = (IDog)Class.forName("Dog").newInstance();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    return dog;
    }
    }其它地方用的时候调用 DogFactory.createDog()来得到IDog的实例, 调用相应的方法。
      

  13.   

    有一个地方写错了 
    public class interface IDog      ->    public interface IDog
      

  14.   

    想法挺好,不过会产生运行时的异常或是通不过编译。因为厂商的类中的方法都是被声明为public native int 型的JNI调用,根本无法被提炼成接口,即就算能提炼成接口也会使Dog类在通过JNI接口访问DLL库时出现“不安全链接”的运行时异常。这是因为一个含有JNI调用的类,其所有方法类型包括非私有字段变量都是不能改变的,把一个native方法改成非native方法是无法正常运行的,估计编译都通不过。我花了一个多小时写了个有包名的包装类,该类用java反射机制来调用厂商的无包名类,解决了无法调用厂商无包名类的问题。看来只有这种笨办法才能解决此问题了真怀疑厂商做的java加密狗调用类是否被人做为商业用途用过?为什么这么明显又容易解决的问题都没解决。看来java项目中使用加密狗的可能很少,要不就是他的产品销量太小。
      

  15.   

    public class Dog implements yourpackage.IDog
     dog = (IDog)Class.forName("Dog").newInstance();
    上面这两句是通不过的。
    因为厂商的Dog类中的所有方法是native类型,还包括许多public类型常量字段,不可以映射到非native的接口。
      

  16.   

    楼主,你真的试过了么?解决问题不能光靠想象。
    用native方法实现接口是可以的, 这我两年前就试过了,刚才又试了一下,结果还是一样。>>>"这是因为一个含有JNI调用的类,其所有方法类型包括非私有字段变量都是不能改变的。"
    没有这回事。只要这个类的包名、类名以及native方法的声明没有变化,对应的dll就不需要重新编译,其他的非native方法和字段可以随便改,这个我也试过的。至于那些public类型常量字段,完全可以从Dog类里面删掉,提到IDog接口里面,不会影响到Dog类的编译,不信的话你可以自己试一下。使用这种方法还有一个好处,就是如果你的IDE支持重构的话,就可以使用Extract Interface 功能自动从Dog类生成IDog接口,连复制修改代码的手续都省了。不过楼主你既然不怕麻烦,自己已经用反射的方法实现了,那就算了。加密狗的厂商不愿意给你加包名就是因为包名改了,对应的.h文件需要重新生成,对应的.c文件里的所有函数名也都需要改,然后还要重新编译dll。而且为了支持其他不想加包名的客户,原来的java文件、.h文件和.c文件都还要保留,这样就需要维护两套源程序。要是我大概也会觉得麻烦, 不过那也没办法,谁让他们早点没考虑到这个问题呢。
    后面是实验用到的所有文件,楼主你要是有兴趣就自己试一下,没兴趣的话就算了,反正不管简单办法还是苯办法,达到目的就行。
      

  17.   

    //Dog.java
    public class Dog implements yourpackage.IDog {
    //这两个常量移到IDog接口里去了
    //public static final int TEST1 = 100;
    //public static final String TEST2 = "Hello"; static {
    try
    {
    System.loadLibrary("dog");
    }
    catch (Exception e)
    {
    e.printStackTrace();
    }
    }
    //native 方法也可以实现接口
    public native void method1();
    public native int method2(); //底下这些字段和构造方法是在dll生成之后新加的,并没有影响到native方法的调用
    /////////////////////////////////////////
    private int a;
    private String b; public Dog()
    {
    System.out.println("Create new Dog");
    a = 1;
    b = "test";
    System.out.println("TEST1=" + TEST1);
    System.out.println("TEST2=" + TEST2);
    }
    }//IDog.java
    package yourpackage;public interface IDog {
    public static final int TEST1 = 100;
    public static final String TEST2 = "Hello"; public void method1();
    public int method2();
    }//DogFactory.java
    package yourpackage;public class DogFactory {
    private static IDog dog = null; public static IDog createDog() {
    if (dog == null) {
    try {
    dog = (IDog)Class.forName("Dog").newInstance();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    return dog;
    }
    }//TestDog.java
    package yourpackage;public class TestDog
    {
    public static void main(String[] args) 
    {
    IDog dog = DogFactory.createDog();
    dog.method1();
    System.out.println(dog.method2());
    }
    }/* Dog.h */
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class Dog */#ifndef _Included_Dog
    #define _Included_Dog
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     Dog
     * Method:    method1
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_Dog_method1
      (JNIEnv *, jobject);/*
     * Class:     Dog
     * Method:    method2
     * Signature: ()I
     */
    JNIEXPORT jint JNICALL Java_Dog_method2
      (JNIEnv *, jobject);#ifdef __cplusplus
    }
    #endif
    #endif
    /* Dog.c */
    #include "jni.h"
    #include "Dog.h"JNIEXPORT void JNICALL Java_Dog_method1(JNIEnv* env, jobject obj) 
    {
    printf("method1 invoked\n");
    }
    JNIEXPORT jint JNICALL Java_Dog_method2(JNIEnv* env, jobject obj)
    {
    printf("method2 invoked\n"); return 999;
    }
      

  18.   

    gtlang78() 说的没错。
    我回去试了一下,确实含有native接口的方法的类也能造型到接口。这个方法解决无名包的导入问题可能是最简单的解决办法了吧。谢谢指点。