Implementation:Risingwavelabs Risingwave DynMethods
| Knowledge Sources | |
|---|---|
| Domains | Reflection, Iceberg, Utilities |
| Language | Java |
| Lines | 522 |
| Last Updated | 2026-02-09 07:00 GMT |
Overview
Utility class providing a builder pattern for dynamically locating and invoking Java methods by reflection, ported from the Apache Iceberg project (originally from parquet-common).
Description
DynMethods is a utility class (with a private constructor) that enables runtime method discovery and invocation through Java reflection. It is part of the Apache Iceberg common utilities included in the RisingWave Iceberg sink connector module. The class provides several nested types:
- UnboundMethod -- A wrapper around java.lang.reflect.Method that provides typed invocation via invoke(Object target, Object... args) and invokeChecked(Object target, Object... args) (which throws checked exceptions). Handles variable-argument methods by tracking argument length. Provides bind(Object receiver) to create a BoundMethod, asStatic() to create a StaticMethod, and isStatic() / isNoop() checks. Includes a singleton NOOP instance that performs no operation and returns null.
- BoundMethod -- Wraps an UnboundMethod bound to a specific receiver object. Provides invoke(Object... args) and invokeChecked(Object... args).
- StaticMethod -- Wraps an UnboundMethod for static method invocation (receiver is always null). Provides invoke(Object... args) and invokeChecked(Object... args).
- Builder -- Fluent builder that searches for methods across multiple candidate classes:
- impl(String className, String methodName, Class<?>... argClasses) -- Looks up a public method by class name.
- impl(String className, Class<?>... argClasses) -- Uses the builder's method name.
- impl(Class<?> targetClass, String methodName, Class<?>... argClasses) -- Looks up a public method on a known class.
- impl(Class<?> targetClass, Class<?>... argClasses) -- Uses the builder's method name.
- hiddenImpl(...) -- Looks up private/protected methods, making them accessible via AccessController.doPrivileged.
- ctorImpl(Class<?> targetClass, Class<?>... argClasses) -- Delegates to DynConstructors.Builder for constructor lookup.
- ctorImpl(String className, Class<?>... argClasses) -- Constructor lookup by class name.
- orNoop() -- Falls back to the NOOP method if no implementation is found.
- build() / buildChecked() -- Returns the found UnboundMethod or throws.
- build(Object receiver) / buildChecked(Object receiver) -- Returns a BoundMethod.
- buildStatic() / buildStaticChecked() -- Returns a StaticMethod.
- MakeAccessible -- A PrivilegedAction that calls setAccessible(true) on hidden methods.
Usage
Used internally by the Iceberg sink connector for reflective method invocation required by Iceberg catalog operations, enabling dynamic method dispatch without compile-time coupling to specific Iceberg internal implementations.
Code Reference
Source Location
- Repository: risingwave
- File: java/connector-node/risingwave-sink-iceberg/src/main/java/org/apache/iceberg/common/DynMethods.java
- Lines: 1-522
Signature
public class DynMethods {
private DynMethods() {}
public static class UnboundMethod {
public <R> R invokeChecked(Object target, Object... args) throws Exception;
public <R> R invoke(Object target, Object... args);
public BoundMethod bind(Object receiver);
public boolean isStatic();
public boolean isNoop();
public StaticMethod asStatic();
}
public static class BoundMethod {
public <R> R invokeChecked(Object... args) throws Exception;
public <R> R invoke(Object... args);
}
public static class StaticMethod {
public <R> R invokeChecked(Object... args) throws Exception;
public <R> R invoke(Object... args);
}
public static Builder builder(String methodName);
public static class Builder {
public Builder(String methodName);
public Builder loader(ClassLoader newLoader);
public Builder orNoop();
public Builder impl(String className, String methodName, Class<?>... argClasses);
public Builder impl(String className, Class<?>... argClasses);
public Builder impl(Class<?> targetClass, String methodName, Class<?>... argClasses);
public Builder impl(Class<?> targetClass, Class<?>... argClasses);
public Builder ctorImpl(Class<?> targetClass, Class<?>... argClasses);
public Builder ctorImpl(String className, Class<?>... argClasses);
public Builder hiddenImpl(String className, String methodName, Class<?>... argClasses);
public Builder hiddenImpl(String className, Class<?>... argClasses);
public Builder hiddenImpl(Class<?> targetClass, String methodName, Class<?>... argClasses);
public Builder hiddenImpl(Class<?> targetClass, Class<?>... argClasses);
public UnboundMethod build();
public BoundMethod build(Object receiver);
public UnboundMethod buildChecked() throws NoSuchMethodException;
public BoundMethod buildChecked(Object receiver) throws NoSuchMethodException;
public StaticMethod buildStatic();
public StaticMethod buildStaticChecked() throws NoSuchMethodException;
}
}
Import
import org.apache.iceberg.common.DynMethods;
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| methodName | String | Yes | Name of the method to locate (passed to builder constructor) |
| className | String | No | Fully qualified class name to search for the method (resolved via Class.forName) |
| targetClass | Class<?> | No | Class instance to search for the method |
| argClasses | Class<?>[] | Varies | Parameter types for method signature matching |
| receiver / target | Object | Varies | Object instance for method invocation (required for non-static methods) |
| args | Object[] | Varies | Arguments to pass to the invoked method |
Outputs
| Name | Type | Description |
|---|---|---|
| UnboundMethod | DynMethods.UnboundMethod | Reflective method invoker not bound to a specific receiver |
| BoundMethod | DynMethods.BoundMethod | Reflective method invoker bound to a specific receiver object |
| StaticMethod | DynMethods.StaticMethod | Reflective invoker for static methods |
| R (generic) | Object | Return value of the invoked method |
Exceptions
| Exception | Condition |
|---|---|
| NoSuchMethodException | No matching method found (from buildChecked methods) |
| RuntimeException | No matching method found (from build methods) or invocation error |
| Exception | Checked exceptions from the invoked method (from invokeChecked) |
| IllegalStateException | Attempting to bind a static method or call asStatic on a non-static method |
| IllegalArgumentException | Receiver class is incompatible with the method's declaring class |
Usage Examples
Invoking a Hidden Method
// Find and invoke a private method "computeHash" on SomeClass
DynMethods.UnboundMethod method = DynMethods.builder("computeHash")
.hiddenImpl(SomeClass.class, "computeHash", String.class)
.build();
String result = method.invoke(someInstance, "inputData");
Static Method with Fallback to NOOP
// Try multiple candidate classes for a static "initialize" method
DynMethods.StaticMethod initMethod = DynMethods.builder("initialize")
.impl("com.example.NewCatalog", "initialize", Configuration.class)
.impl("com.example.LegacyCatalog", "initialize", Configuration.class)
.orNoop()
.buildStatic();
initMethod.invoke(config); // No-op if neither class is found
Bound Method Invocation
DynMethods.BoundMethod getter = DynMethods.builder("getMetadata")
.impl(CatalogTable.class, "getMetadata")
.build(tableInstance);
TableMetadata metadata = getter.invoke();