/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed 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.
 */
import java.lang.reflect.*;

public class HotProxy {

  public static final String testName = "HotProxy";

  interface MyInterface {
    void voidFoo();
  }

  static void check(boolean x) {
    if (!x) {
      throw new AssertionError(testName + " Check failed");
    }
  }

  static class MyInvocationHandler implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) {
      check(proxy instanceof Proxy);
      check(method.getDeclaringClass() == MyInterface.class);
      return null;
    }
  }

  static void testProxy() {
    MyInvocationHandler myHandler = new MyInvocationHandler();
    MyInterface proxyMyInterface =
        (MyInterface)Proxy.newProxyInstance(HotProxy.class.getClassLoader(),
                                            new Class<?>[] { MyInterface.class },
                                            myHandler);
    // Invoke the proxy method multiple times to ensure it becomes hot and the JIT handles it.
    for (int i = 0; i < 0x10000; i++) {
      proxyMyInterface.voidFoo();
    }
  }

  public static void main(String args[]) {
    testProxy();
  }
}
