2010-08-13 11 views
2

J'essaie d'envoyer des objets à partir de faisceaux via un ensemble de communication dédié vers un autre cadre. Pour la communication, j'utilise la sérialisation standard Java (avec ObjectStreams) sur TCP/IP.Désérialisation de tableaux de type personnalisé dans OSGi

Le flux de communication est le suivant: Un expéditeur-faisceau transmettra des objets sérialisables à un expéditeur de transmission qui sérialisera les objets et les enverra via TCP/IP à un transmetteur-récepteur. Le récepteur va ensuite désérialiser les objets reçus et les transmettre au récepteur. Comme l'architecture de chargement de classe OSGi est différente de l'architecture native, je dois faire un peu de bidouille avec le classloader: Comme je suppose que le récepteur-bundle doit connaître les classes qu'il reçoit (= les a-t-il importées ou autrement accessibles? par son chargeur de classe), j'utilise le chargeur de classe du récepteur au lieu du transmetteur-récepteur pour charger la classe. (Via la méthode Bundle.loadClass (..)). Cela fonctionne très bien pour les classes personnalisées, mais cela ne fonctionne pas pour les tableaux de types personnalisés. (qui ne sont pas connus du classloader d'émission-réception, mais au récepteur faisceau.)

Edit: ObjectInputStream.readObject (...) jette un ClassNotFoundException, si elle essaie de désérialiser un tableau. (Je suppose que cette exception provient de la méthode Bundle.loadClass (...) du récepteur-bundle.)

Il fonctionne avec java.util.List ou d'autres classes Serializable. Il fonctionne également pour les types personnalisés qui contiennent des champs d'autres types personnalisés tant qu'ils ne sont pas des tableaux. Donc la question est: Y a-t-il une différence dans la façon dont les tableaux sont de/sérialisés? Ou sont-ils chargés différemment?

Répondre

3

Je suppose que vous avez implémenté ObjectInputStream.resolveClass en utilisant directement Bundle.loadClass. Si oui, vous rencontrez ce problème: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6516909

Fondamentalement, ClassLoader.loadClass n'a jamais été destiné à être utilisé pour les classes de tableau. Le moyen le plus simple de charger des classes de tableau est d'utiliser Class.forName. Malheureusement, il n'y a pas de moyen facile de le faire avec OSGi. Vous aurez soit besoin d'un proxy Bundle ClassLoader, ou vous aurez besoin de faire un peu de pré-traitement sur les noms de classe pour vous assurer que vous ne passez pas des tableaux directement à loadClass:

public static Class<?> bundleClassForName(Bundle bundle, String name) throws ClassNotFoundException { 
    int length = name.length(); 
    if (length > 0 && name.charAt(0) == '[') { 
     int pos = 1; 
     while (pos < length && name.charAt(pos) == '[') { 
      pos++; 
     } 

     if (pos < name.length()) { 
      if (name.charAt(pos) != 'L') { 
       return Class.forName(name); 
      } 

      if (name.charAt(length - 1) == ';') { 
       String componentName = name.substring(pos + 1, length - 1); 
       Class<?> klass = bundle.loadClass(componentName); 
       ClassLoader loader = klass.getClassLoader(); 
       return Class.forName(name, false, loader); 
      } 
     } 
    } 

    return bundle.loadClass(name); 
} 
+0

C'est vrai, nous sommes en cours d'exécution dans ce bug ici .... une solution de contournement que nous avons essayé est en utilisant Dynamic-Import. Cependant, actuellement, nous évitons simplement d'utiliser des tableaux. – Arvodan