2016-10-17 9 views
1

Я пытаюсь сериализовать хэшмапы и коллекции двух пользовательских классов (содержащих больше хэш-карт и коллекций).Сериализация Kryo вызвала фатальную ошибку времени выполнения Java с пользовательскими объектами

Class1: NodeStorage.java

@NotNull 
private final String id; 

@Nullable 
private String type; 

@Nullable 
private HashMap<String, String> properties; 

Class2: RelationshipStorage.java

@NotNull 
private final String id; 

@Nullable 
private String type; 

@Nullable 
private HashMap<String, String> properties; 

@NotNull 
private final NodeStorage startNode; 

@NotNull 
private final NodeStorage endNode; 

коллекции сериализовать:

private HashMap<NodeStorage, NodeStorage> readsSetNode; 
private HashMap<NodeStorage, NodeStorage> updateSetNode; 
private ArrayList<NodeStorage>   deleteSetNode; 
private ArrayList<NodeStorage>   createSetNode; 

private HashMap<RelationshipStorage, RelationshipStorage> readsSetRelationship; 
private HashMap<RelationshipStorage, RelationshipStorage> updateSetRelationship; 
private ArrayList<RelationshipStorage>     deleteSetRelationship; 
private ArrayList<RelationshipStorage>     createSetRelationship; 

То, что я пытался до сих пор:

kryo.register(NodeStorage.class, 1); 
    kryo.register(RelationshipStorage.class, 2); 
    kryo.register(HashMap.class, mapSerializer); 

    mapSerializer.setKeyClass(NodeStorage.class, kryo.getSerializer(NodeStorage.class)); 
    mapSerializer.setKeyClass(RelationshipStorage.class, kryo.getSerializer(RelationshipStorage.class)); 
    mapSerializer.setValuesCanBeNull(false); 
    mapSerializer.setKeysCanBeNull(false); 
    listSerializer.setElementClass(NodeStorage.class, kryo.getSerializer(NodeStorage.class)); 
    listSerializer.setElementClass(RelationshipStorage.class, kryo.getSerializer(RelationshipStorage.class)); 
    listSerializer.setElementsCanBeNull(false); 


    public byte[] serialize() 
{ 
    ByteArrayOutputStream stream = new ByteArrayOutputStream(); 
    Output output = new Output(stream); 
    mapSerializer.write(kryo, output, readsSetNode); 
    byte[] bytes = output.toBytes(); 
    output.close(); 
    return bytes; 
} 

Я попробовал это с kryo.writeclassandobject, но это не сработало. Я получаю:

> > # 
> # A fatal error has been detected by the Java Runtime Environment: 
> # 
> # SIGSEGV (0xb) at pc=0x00007f92f7f6efe0, pid=4637, tid=0x00007f92f94fd700 
> # 
> # JRE version: OpenJDK Runtime Environment (8.0_102-b14) (build 1.8.0_102-b14) 
> # Java VM: OpenJDK 64-Bit Server VM (25.102-b14 mixed mode linux-amd64 compressed oops) 
> # Problematic frame: 
> # V [libjvm.so+0x787fe0] 
> # 
> # Core dump written 

Полный код по адресу: https://github.com/Raycoms/thesis

декларации:

private Kryo kryo = new Kryo(); 
MapSerializer  mapSerializer = new MapSerializer(); 
CollectionSerializer listSerializer = new CollectionSerializer(); 
+0

Можете ли вы попытаться начать с 100 вместо 1 в качестве первого идентификатора? См. Https://github.com/EsotericSoftware/kryo/issues/430 – MartinGrotzke

+0

. Установите его на 100 и 200, ничего не изменив. Такое же сообщение об ошибке. – user2524707

+1

Может быть связанным с потоком - см. [Этот вопрос GitHub] (https://github.com/EsotericSoftware/kryo/issues/426#issuecomment-243239835), который кажется схожим. С помощью [thread-pooling readme] (https://github.com/EsotericSoftware/kryo#pooling-kryo-instances), связанного с ним, помог хотя бы один другой кодер.(Обнаружено это путем проверки трассировки стека в [вашем журнале] (https://github.com/Raycoms/thesis/blob/master/hs_err_pid11037.log).) – cxw

ответ

2

Kryo не поточно-, и практически любая программа Java имеет несколько потоков происходит. Например, ваш log file показывает, что у вас есть 25 потоков, запущенных во время сбоя. Несмотря на то, что ваш экземпляр Kryo является конфиденциальным, ошибка находится глубоко в недрах Kryo, и там могут быть потоковые или JVM-взаимодействия, которые не находятся под вашим контролем.

Попробуйте подход поточно-бассейн, цитируемый ниже, подробно описаны в Kryo readme:

import com.esotericsoftware.kryo.Kryo; 
import com.esotericsoftware.kryo.pool.*; 

KryoFactory factory = new KryoFactory() { 
    public Kryo create() { 
    Kryo kryo = new Kryo(); 
    // configure kryo instance, customize settings 
    return kryo; 
    } 
}; 
// Build pool with SoftReferences enabled (optional) 
KryoPool pool = new KryoPool.Builder(factory).softReferences().build(); 

Тогда в вашей serialize() функции:

Kryo kryo = pool.borrow(); 
<... the rest of your code in serialize() before the return...> 
pool.release(kryo); 
return bytes; 

Как README указывает, вы также можете использовать обратный вызов:

Окончательный код
// or use a callback to work with kryo - no need to borrow/release, 
// that's done by `run`. 
String value = pool.run(new KryoCallback() { 
    public String execute(Kryo kryo) { 
    return kryo.readObject(input, String.class); 
    } 
}); 

OP в

Опубликовано здесь с замечанием OP так, чтобы другие могли читать его более легко. OP не в состоянии использовать mapSerializer в конце концов, но был в состоянии сериализовать, используя этот код:

private byte[] serialize() { 
    KryoPool pool = new KryoPool.Builder(factory).softReferences().build(); 
    Kryo kryo = pool.borrow(); 
    Output output = new Output(0, 1024); 
    kryo.writeClassAndObject(output, readsSetNode); 
    byte[] bytes = output.toBytes(); 
    output.close(); 
    pool.release(kryo); 
    return bytes; 
} 

Примечание Как @MartinGrotzke отметил, в this issue, если вы используете kryo.register(class, id), убедитесь, что id>=10.

+0

я сломал его с помощью карты сериалайзер: Kryo Kryo = pool.borrow(); MapSerializer mapSerializer = новый MapSerializer(); mapSerializer.setKeyClass (NodeStorage.class, kryo.getSerializer (NodeStorage.class)); mapSerializer.setKeyClass (RelationshipStorage.class, kryo.getSerializer (RelationshipStorage.class)); mapSerializer.setValuesCanBeNull (ложь); mapSerializer.setKeysCanBeNull (ложь); выход выход = новый выход (0 , 1024); mapSerializer.write (kryo, output, readsSetNode); byte [] bytes = output.toBytes(); – user2524707

+0

Теперь он работает только с kryo. Большое спасибо. – user2524707

+0

К сожалению, я вообще не смог использовать mapSerializer. Но, сериализируя его, используя следующий код работал: private byte [] serialize() { KryoPool pool = new KryoPool.Builder (завод) .softReferences(). Build(); Kryo kryo = pool.borrow(); Выходной выход = новый Выход (0, 1024); kryo.writeClassAndObject (output, readsSetNode); byte [] bytes = output.toBytes(); output.close(); pool.release (kryo); возвратные байты; } – user2524707