Protobuf serialization for pre-existing objects with runtime schema generation and polymorphic type handling
—
Environment configuration, optimization settings, and utility classes for controlling runtime behavior and performance characteristics. The RuntimeEnv class provides access to system-wide configuration options and utility methods for object instantiation.
Global configuration constants that control default behavior across the protostuff-runtime library.
/**
* Java version detection - true if running on Java 9 or higher
*/
public static final boolean JAVA_9_AND_ABOVE;
/**
* Default enum serialization mode - true to serialize by name, false by ordinal
*/
public static final boolean ENUMS_BY_NAME;
/**
* Auto-load polymorphic classes when encountered during deserialization
*/
public static final boolean AUTO_LOAD_POLYMORPHIC_CLASSES;
/**
* Preserve null elements in collections and arrays
*/
public static final boolean PRESERVE_NULL_ELEMENTS;
/**
* Enable morphing for non-final POJO types in polymorphic scenarios
*/
public static final boolean MORPH_NON_FINAL_POJOS;
/**
* Enable morphing for collection interfaces (List, Set, Queue, etc.)
*/
public static final boolean MORPH_COLLECTION_INTERFACES;
/**
* Enable morphing for map interfaces
*/
public static final boolean MORPH_MAP_INTERFACES;
/**
* Use collection schema on repeated fields instead of simple repeated values
*/
public static final boolean COLLECTION_SCHEMA_ON_REPEATED_FIELDS;
/**
* Use POJO schema on collection fields for complex object handling
*/
public static final boolean POJO_SCHEMA_ON_COLLECTION_FIELDS;
/**
* Use POJO schema on map fields for complex object handling
*/
public static final boolean POJO_SCHEMA_ON_MAP_FIELDS;
/**
* Enable sun.misc.Unsafe usage for performance optimizations
*/
public static final boolean USE_SUN_MISC_UNSAFE;
/**
* Always use sun.reflect.ReflectionFactory for object instantiation
*/
public static final boolean ALWAYS_USE_SUN_REFLECTION_FACTORY;
/**
* Never use sun.reflect.ReflectionFactory for object instantiation
*/
public static final boolean NEVER_USE_SUN_REFLECTION_FACTORY;
/**
* Default ID strategy instance used throughout the library
*/
public static final IdStrategy ID_STRATEGY;Utility methods for creating optimized object instantiators that can bypass constructors when needed.
/**
* Create an instantiator for the specified class
* The instantiator will use the most efficient method available:
* - Constructor with no arguments if available
* - sun.reflect.ReflectionFactory if enabled and available
* - Unsafe allocation if enabled and available
*
* @param clazz The class to create instantiator for
* @return Instantiator instance for the class
*/
public static <T> Instantiator<T> newInstantiator(Class<T> clazz);Abstract base class for object instantiation with performance optimizations.
/**
* Abstract base class for optimized object instantiation
*/
public abstract static class Instantiator<T> {
/**
* Create a new instance of the target class
* Implementation uses the most efficient instantiation method available
*
* @return New instance of T
*/
public abstract T newInstance();
}import io.protostuff.runtime.RuntimeEnv;
import io.protostuff.runtime.RuntimeSchema;
import io.protostuff.Schema;
// Check environment capabilities
if (RuntimeEnv.JAVA_9_AND_ABOVE) {
System.out.println("Running on Java 9+");
}
if (RuntimeEnv.USE_SUN_MISC_UNSAFE) {
System.out.println("Unsafe optimizations enabled");
}
// Use default ID strategy
Schema<User> schema = RuntimeSchema.getSchema(User.class, RuntimeEnv.ID_STRATEGY);// Create instantiator for performance-critical paths
RuntimeEnv.Instantiator<User> userInstantiator = RuntimeEnv.newInstantiator(User.class);
// Use instantiator in performance-critical code
public User createUser() {
User user = userInstantiator.newInstance();
// Initialize user fields as needed
return user;
}
// Create instantiators for multiple types
RuntimeEnv.Instantiator<Order> orderInstantiator = RuntimeEnv.newInstantiator(Order.class);
RuntimeEnv.Instantiator<Product> productInstantiator = RuntimeEnv.newInstantiator(Product.class);/**
* Service that adapts behavior based on runtime configuration
*/
public class SerializationService {
private final IdStrategy strategy;
public SerializationService() {
// Use different strategies based on configuration
if (RuntimeEnv.PRESERVE_NULL_ELEMENTS && RuntimeEnv.ENUMS_BY_NAME) {
int flags = IdStrategy.PRESERVE_NULL_ELEMENTS | IdStrategy.ENUMS_BY_NAME;
this.strategy = new DefaultIdStrategy(flags);
} else {
this.strategy = RuntimeEnv.ID_STRATEGY;
}
}
public <T> Schema<T> getSchema(Class<T> clazz) {
return RuntimeSchema.getSchema(clazz, strategy);
}
public boolean supportsComplexCollections() {
return RuntimeEnv.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;
}
public boolean supportsUnsafeOptimizations() {
return RuntimeEnv.USE_SUN_MISC_UNSAFE;
}
}The runtime environment reads configuration from system properties. You can override defaults by setting these properties:
// Set via system properties or JVM arguments
// Enum serialization: -Dprotostuff.runtime.enums_by_name=true
System.setProperty("protostuff.runtime.enums_by_name", "true");
// Auto-load classes: -Dprotostuff.runtime.auto_load_polymorphic_classes=true
System.setProperty("protostuff.runtime.auto_load_polymorphic_classes", "true");
// Preserve nulls: -Dprotostuff.runtime.preserve_null_elements=true
System.setProperty("protostuff.runtime.preserve_null_elements", "true");
// Morphing options
System.setProperty("protostuff.runtime.morph_non_final_pojos", "true");
System.setProperty("protostuff.runtime.morph_collection_interfaces", "true");
System.setProperty("protostuff.runtime.morph_map_interfaces", "true");
// Schema options
System.setProperty("protostuff.runtime.collection_schema_on_repeated_fields", "true");
System.setProperty("protostuff.runtime.pojo_schema_on_collection_fields", "true");
System.setProperty("protostuff.runtime.pojo_schema_on_map_fields", "true");// Unsafe usage: -Dprotostuff.runtime.use_sun_misc_unsafe=false
System.setProperty("protostuff.runtime.use_sun_misc_unsafe", "false");
// Reflection factory control
System.setProperty("protostuff.runtime.always_use_sun_reflection_factory", "true");
System.setProperty("protostuff.runtime.never_use_sun_reflection_factory", "true");
// Field factory selection
System.setProperty("protostuff.runtime.use_reflection_field_factory", "true");/**
* Factory with cached instantiators for better performance
*/
public class ObjectFactory {
private static final Map<Class<?>, RuntimeEnv.Instantiator<?>> INSTANTIATORS =
new ConcurrentHashMap<>();
@SuppressWarnings("unchecked")
public static <T> T newInstance(Class<T> clazz) {
RuntimeEnv.Instantiator<T> instantiator =
(RuntimeEnv.Instantiator<T>) INSTANTIATORS.computeIfAbsent(
clazz, RuntimeEnv::newInstantiator
);
return instantiator.newInstance();
}
// Pre-populate cache for known types
static {
preloadInstantiators(User.class, Order.class, Product.class);
}
private static void preloadInstantiators(Class<?>... classes) {
for (Class<?> clazz : classes) {
INSTANTIATORS.put(clazz, RuntimeEnv.newInstantiator(clazz));
}
}
}/**
* Schema factory that creates optimized schemas based on environment
*/
public class OptimizedSchemaFactory {
private static final IdStrategy OPTIMIZED_STRATEGY;
static {
// Build strategy based on environment capabilities
int flags = 0;
if (RuntimeEnv.ENUMS_BY_NAME) {
flags |= IdStrategy.ENUMS_BY_NAME;
}
if (RuntimeEnv.PRESERVE_NULL_ELEMENTS) {
flags |= IdStrategy.PRESERVE_NULL_ELEMENTS;
}
if (RuntimeEnv.COLLECTION_SCHEMA_ON_REPEATED_FIELDS) {
flags |= IdStrategy.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;
}
if (RuntimeEnv.POJO_SCHEMA_ON_COLLECTION_FIELDS) {
flags |= IdStrategy.POJO_SCHEMA_ON_COLLECTION_FIELDS;
}
OPTIMIZED_STRATEGY = new DefaultIdStrategy(flags);
}
public static <T> Schema<T> getOptimizedSchema(Class<T> clazz) {
return RuntimeSchema.getSchema(clazz, OPTIMIZED_STRATEGY);
}
public static IdStrategy getOptimizedStrategy() {
return OPTIMIZED_STRATEGY;
}
}/**
* Utility for checking reflection capabilities
*/
public class ReflectionCapabilities {
public static boolean hasUnsafeSupport() {
return RuntimeEnv.USE_SUN_MISC_UNSAFE;
}
public static boolean hasReflectionFactorySupport() {
return !RuntimeEnv.NEVER_USE_SUN_REFLECTION_FACTORY;
}
public static boolean isModernJava() {
return RuntimeEnv.JAVA_9_AND_ABOVE;
}
public static String getCapabilitiesReport() {
StringBuilder report = new StringBuilder();
report.append("Runtime Capabilities:\n");
report.append("- Java 9+: ").append(RuntimeEnv.JAVA_9_AND_ABOVE).append("\n");
report.append("- Unsafe: ").append(RuntimeEnv.USE_SUN_MISC_UNSAFE).append("\n");
report.append("- ReflectionFactory: ").append(!RuntimeEnv.NEVER_USE_SUN_REFLECTION_FACTORY).append("\n");
report.append("- Enums by name: ").append(RuntimeEnv.ENUMS_BY_NAME).append("\n");
report.append("- Preserve nulls: ").append(RuntimeEnv.PRESERVE_NULL_ELEMENTS).append("\n");
return report.toString();
}
}All RuntimeEnv constants and methods are thread-safe:
The default ID_STRATEGY instance is also thread-safe and can be shared across threads.
Install with Tessl CLI
npx tessl i tessl/maven-io-protostuff--protostuff-runtime