I want to invoke static method of Java 8 interface using reflection API.
public interface TimeClient {
static void testStatic() {
System.out.println("In the Static");
}
}
I am able to invoke default method of Interface but unable to invoke static method.
I see no problems:
TimeClient.class.getDeclaredMethod("testStatic").invoke(null);
Works without problems and prints "In the Static". The getMethod also works as expected:
TimeClient.class.getMethod("testStatic").invoke(null);
Related
I use PicoCLI to parse the arguments. I need to specify setStopAtPositional(true) for one of the subcommands. Is there a way to do this with an annotation? Currently I do this:
cmd.getSubcommands().get("submit").setStopAtPositional(true);
But it would be better to specify it at the method where the submit command is specified to have entire specification in one place.
My class has this structure:
#Command(...)
public class CommandLine implements Callable<Void> {
#Command(...)
public void submit( ... options) {
}
}
Picocli allows different parser configuration for each subcommand, and what you suggest works for your example.
There is currently no annotation API to configure the parser, it may be an idea to add this in a future release.
Note that setting the parser configuration via the CommandLine object will change it for that command and its full hierarchy of subcommands and sub-subcommands.
If you want to change the parser configuration for a single command (without impacting its subcommands), use CommandLine.getCommandSpec().parser() to get its ParserSpec object and do the configuration on that ParserSpec object (example below).
The question did not mention this, but there may be a concern that it's a bit clunky in picocli 3.9.x to invoke the program after configuration, with the parseWithHandler method. This becomes a bit nicer with the execute method added in picocli 4.0.
For example:
#Command(subcommands = B.class)
class A implements Callable<Integer> {
}
#Command(name = "B")
class B implements Callable<Integer> {
#Command
public int subB(... options) {
}
}
public static void main(String... args) {
CommandLine cmdA = new CommandLine(new A());
// Example 1: configure the B command _and_ its subcommands
cmdA.getSubcommands().get("B").setStopAtPositional(true);
// Example 2: configure the A command _only_ (not the subcommands)
cmdA.getCommandSpec().parser().caseInsensitiveEnumValuesAllowed(true);
// parse input and run the command
int exitCode = cmdA.execute(args);
System.exit(exitCode);
}
Picocli has to introspect the command tree. Doing so it needs to load the domain object classes for every Command which slows down the jvm startup.
What options are there to avoid this startup lag? One solution I've come up with is described in https://github.com/remkop/picocli/issues/482:
I am using reflection to postpone any class loading until after the command is selected. This way only the command classes themselves are loaded and finally the classes which implement the single command requested by the user:
abstract class BaseCommand implements Runnable {
interface CommandExecutor {
Object doExecute() throws Exception;
}
// find the CommandExecutor declared at the BaseCommand subclass.
protected Object executeReflectively() throws Exception {
Class<?> innerClass = getExecutorInnerClass();
Constructor<?> ctor = innerClass.getDeclaredConstructor(getClass());
CommandExecutor exec = (CommandExecutor) ctor.newInstance(this);
return exec.doExecute();
}
private Class<?> getExecutorInnerClass() throws ClassNotFoundException {
return getClass().getClassLoader().loadClass(getClass().getName() + "$Executor");
}
public void run() {
try {
executeReflectively();
} catch(...){
/// usual stuff
}
}
}
A concrete commend class:
#Command(...)
final class CopyProfile extends BaseCommand {
#Option String source;
#Option String dest;
// class must NOT be static and must be called "Executor"
public class Executor implements CommandExecutor {
#Override
public Object doExecute() throws Exception {
// you can basically wrap your original run() with this boilerplate
// all the CopyProfile's field are in scope!
FileUtils.copy(source, dest);
}
}
}
It seems like https://github.com/remkop/picocli/issues/500 may provide the ultimate solution to this. What are the other options until then?
UPDATE February 2020:
Upgrading to a recent version of picocli should fix this issue.
From the picocli 4.2.0 release notes:
From this release, subcommands are not instantiated until they are matched on the command line. This should improve the startup time for applications with subcommands that do a lot of initialization when they are instantiated.
An alternative that doesn’t require any code changes is to use GraalVM to compile your picocli-based application to a native image.
This article shows how to do this and the resulting startup time is 3 milliseconds.
Lambda translation is a two step process, One: desugaring the lambda into a static method in same class.
public class Main {
public static void main(String[] args) {
Runnable r = () -> System.out.println("Hello");
System.out.println(Arrays.asList(Main.class.getDeclaredMethods()));
}
}
[private static void Main.lambda$main$0(), public static void
Main.main(java.lang.String[])]
Two: generation of a class that implements the Functional Interface.
System.out.println("A class has been generated: " + r.getClass());
System.out.println("That implements a Functional Interface: " + Arrays.asList(r.getClass().getInterfaces()));
A class has been generated: class Main$$Lambda$1/149928006
That implements a Functional Interface: [interface java.lang.Runnable]
Question: What is the need of this static method? Why can't the lambda body be put directly into the interface method? Something like:
class Main$$Lambda$1 {
public void run() {
/* Lambda body here */
}
}
In addition to the correct answers given here (because the current scheme is more efficient, reducing capture/linkage costs for lambdas and reducing code duplication), there are a few other reasons why your idea simply doesn't make sense.
Where would the bytecode come from in the first place? The lambda proxy class is generated at runtime, not compile time. If we were to stuff the bytecode into the proxy class, it would have to come from somewhere. That would mean we'd have to put it into the capturing class file and then copy it into the proxy class. Here, it just lives in the capturing class and we're done.
Access control. What if the lambda body calls a private method? By desugaring it into the capturing class, it automatically acquires the access control context of the capturing class (which it is logically a part of.) If we put the bytecode in the proxy class, we'd have to do additional magic to give it the right access control context.
Because this way it's actually cheaper. Generating a lambda from the method on the fly during the first invocation is better than loading a separate class via class loader. Internally it uses UNSAFE.defineAnonymousClass which is more light-weight class than normal. Such "lambda-class" is not bound to any class loader, so can be easily garbage-collected when it's no longer necessary. Also I guess there are plans to make this mechanism even more light-weight and faster. For normal anonymous class this would not be possible as from the point of JVM such classes don't differ from usual classes and much more heavy.
Your test is incomplete.
public class Lambda {
private String hello = "Hello from instance";
public static void main(String[] args) {
Runnable r = () -> System.out.println("Hello");
for (Method m: Lambda.class.getDeclaredMethods()) {
System.out.println(m);
}
}
public void instanceMethodWithAccessToInstanceVariables(){
Runnable r = () -> System.out.println(hello);
}
public void instanceMethodWithoutAccessToInstanceVariables(){
Runnable r = () -> System.out.println("Hello from instance");
}
}
This results in the following:
public void Lambda.instanceMethodWithAccessToInstanceVariables()
public void Lambda.instanceMethodWithoutAccessToInstanceVariables()
private static void Lambda.lambda$instanceMethodWithoutAccessToInstanceVariables$2()
private void Lambda.lambda$instanceMethodWithAccessToInstanceVariables$1()
private static void Lambda.lambda$main$0()
public static void Lambda.main(java.lang.String[])
This clearly shows several cases:
lambdas in static method declare static method
lambdas in instance methods using instance variables declare instance methods
lambdas in instance methods not using instance variables declare static method
The two first are rather logical. Why would you expect a static member to access an instance member? Same for the instance method.
The real question is why does an instance method not using any instance variables declare a static method?
Well, this is also for performance and safety reasons mentioned by Tagir.
I'm attempting to do versioning with ASP.NET Web API. I have created a simple controllerselector that derives from DefaultHttpControllerSelector.
public class MyHttpControllerSelector : DefaultHttpControllerSelector
{
public MyHttpControllerSelector(HttpConfiguration config) : base(config) { }
public override string GetControllerName(HttpRequestMessage request)
{
return "SomeControllerName";
}
}
In my WebApiConfig.Register:
config.MapHttpAttributeRoutes();
config.Services.Replace(typeof(IHttpControllerSelector), new MyHttpControllerSelector(config));
My problem is GetControllerName is never called. I may be misunderstanding the intent of this function, but I have seen plenty of examples, some right from Microsoft that use this method.
What am I missing?
In my case it was because I was not calling config.Routes.MapHttpRoute(). I was just using Attribute Routing. Once I used MapHttpRoute() it seemed to start calling GetControllerName.
I have a servlet that I cannot change (com.sun.jersey.spi.container.servlet.ServletContainer of Jersey RS) . What I can do is create a subclass of it. However, I needed that when the servlet is initialized it runs one function of my subclass. I cannot override the init method because it has the Jersey code.
I tried to use the annotation #PostConstruct on a method to make it run after initialization but it does not work (but it does work under Tomcat 6).
In web.xml the class is set to run on startup.
You should be able to subclass ServletContainer, override init, invoke the superclass method then perform your own logic, i.e.
public class MyServletContainer extends ServletContainer {
public void init() throws ServletException {
super.init();
//... perform custom initialization logic here
}
}
Check if you have some of these jars "commons-annotation.jar, geronimo-annotation_1.1_spec, jboss-annotations-api_1.1_spec" in your webapp lib and remove.