CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-protostuff--protostuff-runtime

Protobuf serialization for pre-existing objects with runtime schema generation and polymorphic type handling

Pending
Overview
Eval results
Files

runtime-environment.mddocs/

Runtime Environment and Configuration

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.

Capabilities

Runtime Environment Constants

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;

Object Instantiation

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);

Instantiator Abstract Class

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();
}

Usage Examples

Basic Environment Configuration

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);

Custom Object Instantiation

// 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);

Configuration-Aware Code

/**
 * 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;
    }
}

System Property Configuration

The runtime environment reads configuration from system properties. You can override defaults by setting these properties:

Core Behavior 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");

Performance Properties

// 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");

Performance Optimization Patterns

Instantiator Caching

/**
 * 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));
        }
    }
}

Environment-Aware Schema Factory

/**
 * 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;
    }
}

Reflection Information

/**
 * 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();
    }
}

Configuration Best Practices

  1. System Properties: Set configuration via system properties for application-wide consistency
  2. Environment Detection: Use environment constants to adapt behavior at runtime
  3. Performance Settings: Enable unsafe and reflection factory optimizations when possible
  4. Null Handling: Configure null preservation based on your data requirements
  5. Enum Serialization: Choose between name-based or ordinal-based enum serialization
  6. Instantiator Caching: Cache instantiators for frequently created objects
  7. Strategy Selection: Use environment-aware strategy creation for optimal performance
  8. Testing: Test with different configurations to ensure compatibility across environments

Thread Safety

All RuntimeEnv constants and methods are thread-safe:

  • Constants: All static final fields are immutable and thread-safe
  • newInstantiator(): Returns thread-safe instantiator instances
  • Instantiator.newInstance(): All implementations are thread-safe
  • Configuration: System property-based configuration is read once at class loading

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

docs

annotations.md

custom-serialization.md

field-access.md

index.md

polymorphic-schemas.md

runtime-environment.md

schema-generation.md

type-strategy.md

tile.json