Skip to content

Commit

Permalink
add class not found cache (#73)
Browse files Browse the repository at this point in the history
* add class not found cache

* add switch to control if use class not found cache

* change dynamic load enable to false

Co-authored-by: 朝望 <[email protected]>
  • Loading branch information
OrezzerO and OrezzerO authored Feb 14, 2022
1 parent e4c4795 commit a71bc56
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 16 deletions.
64 changes: 48 additions & 16 deletions src/main/java/com/caucho/hessian/io/SerializerFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,31 +80,42 @@
*/
public class SerializerFactory extends AbstractSerializerFactory
{
private static final Logger log = Logger.getLogger(SerializerFactory.class.getName());
private static final Logger log = Logger.getLogger(SerializerFactory.class
.getName());

protected static Deserializer OBJECT_DESERIALIZER = new BasicDeserializer(BasicDeserializer.OBJECT);
protected static Deserializer OBJECT_DESERIALIZER = new BasicDeserializer(
BasicDeserializer.OBJECT);

protected static ConcurrentMap _staticSerializerMap;
protected static ConcurrentMap _staticDeserializerMap;
protected static ConcurrentMap _staticTypeMap;
protected static ConcurrentMap _staticSerializerMap;
protected static ConcurrentMap _staticDeserializerMap;
protected static ConcurrentMap _staticTypeMap;

protected Serializer _defaultSerializer;
protected Serializer _defaultSerializer;

// Additional factories
protected ArrayList _factories = new ArrayList();
protected ArrayList _factories = new ArrayList();

protected CollectionSerializer _collectionSerializer;
protected CollectionSerializer _collectionSerializer;

protected Deserializer _hashMapDeserializer;
protected ConcurrentMap _cachedSerializerMap = new ConcurrentHashMap();
protected ConcurrentMap _cachedDeserializerMap = new ConcurrentHashMap();
protected ConcurrentMap _cachedTypeDeserializerMap = new ConcurrentHashMap();
protected Deserializer _hashMapDeserializer;
protected ConcurrentMap _cachedSerializerMap = new ConcurrentHashMap();
protected ConcurrentMap _cachedDeserializerMap = new ConcurrentHashMap();
protected ConcurrentMap _cachedTypeDeserializerMap = new ConcurrentHashMap();

protected boolean _isAllowNonSerializable;
protected boolean _isAllowNonSerializable;

protected ClassNameResolver classNameResolver = ClassNameResolverBuilder.buildDefault();
protected ClassNameResolver classNameResolver = ClassNameResolverBuilder.buildDefault();

protected final static boolean isHigherThanJdk8 = isJava8();
protected final static boolean isHigherThanJdk8 = isJava8();

private Map<ClassLoader, Map<String, Object>> _typeNotFoundMap = new ConcurrentHashMap<ClassLoader, Map<String, Object>>(
8);

private static final Object NOT_FOUND = new Object();
public static final String DYNAMIC_LOAD_ENABLE_KEY = "sofa.serialize.dynamic.load.enable";
private boolean dynamicLoadEnable = Boolean.parseBoolean(System.getProperty(
DYNAMIC_LOAD_ENABLE_KEY,
Boolean.FALSE.toString()));

/**
* Set true if the collection serializer should send the java type.
Expand Down Expand Up @@ -480,13 +491,34 @@ public Deserializer getDeserializer(String type)
deserializer = new ArrayDeserializer(subDeserializer);
}
else {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (!dynamicLoadEnable) {
Map<String, Object> typeMap = _typeNotFoundMap.get(loader);
if (typeMap != null) {
if (typeMap.containsKey(type)) {
return null;
}
}
}

Class cl = Class.forName(type, false, loader);

deserializer = getDeserializer(cl);
} catch (Exception e) {
if (!dynamicLoadEnable) {
Map<String, Object> typeMap = _typeNotFoundMap.get(loader);
if (typeMap == null) {
synchronized (this) {
typeMap = _typeNotFoundMap.get(loader);
if (typeMap == null) {
_typeNotFoundMap.put(loader, new ConcurrentHashMap<String, Object>(8));
typeMap = _typeNotFoundMap.get(loader);
}
}
}
typeMap.put(type, NOT_FOUND);
}
log.log(Level.FINER, e.toString(), e);
}
}
Expand Down
111 changes: 111 additions & 0 deletions src/test/java/com/caucho/hessian/test/SerializerFactoryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.caucho.hessian.test;

import com.caucho.hessian.io.Deserializer;
import com.caucho.hessian.io.SerializerFactory;
import org.junit.Assert;
import org.junit.Test;

import java.awt.Color;
import java.lang.reflect.Field;
import java.util.Map;

/**
* @author zhaowang
* @version : SerializerFactoryTest.java, v 0.1 2021年12月30日 2:35 下午 zhaowang
*/
public class SerializerFactoryTest {

@Test
public void getDeserializerByType() throws Exception {
System.setProperty(SerializerFactory.DYNAMIC_LOAD_ENABLE_KEY, "false");
final SerializerFactory serializerFactory = new SerializerFactory();
Field typeNotFoundMap = serializerFactory.getClass().getDeclaredField("_typeNotFoundMap");
typeNotFoundMap.setAccessible(true);
Map<ClassLoader, Map<String, Object>> classLoaderMap = ((Map<ClassLoader, Map<String, Object>>) typeNotFoundMap
.get(serializerFactory));
ClassLoader cl = Thread.currentThread().getContextClassLoader();

final String testClassName = Color.class.getName();
Deserializer d1 = serializerFactory.getDeserializer(testClassName);
Assert.assertNotNull("TestClass Deserializer!", d1);

String notExist = "com.test.NotExistClass";
Assert.assertNull(classLoaderMap.get(cl));

Deserializer d2 = serializerFactory.getDeserializer(notExist);
Assert.assertNull("NotExistClass Deserializer!", d2);
Assert.assertNotNull(classLoaderMap.get(cl).get(notExist));

Deserializer d3 = serializerFactory.getDeserializer(notExist);
Assert.assertNull("NotExistClass Deserializer!", d3);
System.clearProperty(SerializerFactory.DYNAMIC_LOAD_ENABLE_KEY);
}

@Test
public void getDeserializerByType2() throws Exception {
System.setProperty(SerializerFactory.DYNAMIC_LOAD_ENABLE_KEY, "true");
final SerializerFactory serializerFactory = new SerializerFactory();
Field typeNotFoundMap = serializerFactory.getClass().getDeclaredField("_typeNotFoundMap");
typeNotFoundMap.setAccessible(true);
Map<ClassLoader, Map<String, Object>> classLoaderMap = ((Map<ClassLoader, Map<String, Object>>) typeNotFoundMap
.get(serializerFactory));
ClassLoader cl = Thread.currentThread().getContextClassLoader();

final String testClassName = Color.class.getName();
Deserializer d1 = serializerFactory.getDeserializer(testClassName);
Assert.assertNotNull("TestClass Deserializer!", d1);

String notExist = "com.test.NotExistClass";
Assert.assertNull(classLoaderMap.get(notExist));

Deserializer d2 = serializerFactory.getDeserializer(notExist);
Assert.assertNull("NotExistClass Deserializer!", d2);
Assert.assertNull(classLoaderMap.get(cl));

Deserializer d3 = serializerFactory.getDeserializer(notExist);
Assert.assertNull("NotExistClass Deserializer!", d3);
System.clearProperty(SerializerFactory.DYNAMIC_LOAD_ENABLE_KEY);
}

@Test
public void testDynamicLoadEnableDefaultFalse() throws Exception {
System.clearProperty(SerializerFactory.DYNAMIC_LOAD_ENABLE_KEY);
final SerializerFactory serializerFactory = new SerializerFactory();
Field typeNotFoundMap = serializerFactory.getClass().getDeclaredField("_typeNotFoundMap");
typeNotFoundMap.setAccessible(true);
Map<ClassLoader, Map<String, Object>> classLoaderMap = ((Map<ClassLoader, Map<String, Object>>) typeNotFoundMap
.get(serializerFactory));
ClassLoader cl = Thread.currentThread().getContextClassLoader();

final String testClassName = Color.class.getName();
Deserializer d1 = serializerFactory.getDeserializer(testClassName);
Assert.assertNotNull("TestClass Deserializer!", d1);

String notExist = "com.test.NotExistClass";
Assert.assertNull(classLoaderMap.get(notExist));

Deserializer d2 = serializerFactory.getDeserializer(notExist);
Assert.assertNull("NotExistClass Deserializer!", d2);
Assert.assertNotNull(classLoaderMap.get(cl).get(notExist));

Deserializer d3 = serializerFactory.getDeserializer(notExist);
Assert.assertNull("NotExistClass Deserializer!", d3);
}

}

0 comments on commit a71bc56

Please sign in to comment.