Skip to content

Commit

Permalink
Merging master HEAD into openj9-staging
Browse files Browse the repository at this point in the history
  • Loading branch information
j9build committed Dec 2, 2020
2 parents 3f09cef + 11ff3af commit f702105
Show file tree
Hide file tree
Showing 77 changed files with 2,459 additions and 243 deletions.
1 change: 1 addition & 0 deletions make/autoconf/help.m4
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ AC_DEFUN_ONCE([HELP_PRINT_SUMMARY_AND_WARNINGS],
printf "\n"
printf "Configuration summary:\n"
printf "* Name: $CONF_NAME\n"
printf "* Debug level: $DEBUG_LEVEL\n"
printf "* HS debug level: $HOTSPOT_DEBUG_LEVEL\n"
printf "* JVM variants: $JVM_VARIANTS\n"
Expand Down
33 changes: 17 additions & 16 deletions src/java.base/share/classes/java/io/InputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -577,13 +577,15 @@ public long skip(long n) throws IOException {
* @implSpec
* If {@code n} is zero or negative, then no bytes are skipped.
* If {@code n} is positive, the default implementation of this method
* invokes {@link #skip(long) skip()} with parameter {@code n}. If the
* return value of {@code skip(n)} is non-negative and less than {@code n},
* then {@link #read()} is invoked repeatedly until the stream is {@code n}
* bytes beyond its position when this method was invoked or end of stream
* is reached. If the return value of {@code skip(n)} is negative or
* greater than {@code n}, then an {@code IOException} is thrown. Any
* exception thrown by {@code skip()} or {@code read()} will be propagated.
* invokes {@link #skip(long) skip()} repeatedly with its parameter equal
* to the remaining number of bytes to skip until the requested number
* of bytes has been skipped or an error condition occurs. If at any
* point the return value of {@code skip()} is negative or greater than the
* remaining number of bytes to be skipped, then an {@code IOException} is
* thrown. If {@code skip()} ever returns zero, then {@link #read()} is
* invoked to read a single byte, and if it returns {@code -1}, then an
* {@code EOFException} is thrown. Any exception thrown by {@code skip()}
* or {@code read()} will be propagated.
*
* @param n the number of bytes to be skipped.
* @throws EOFException if end of stream is encountered before the
Expand All @@ -596,20 +598,19 @@ public long skip(long n) throws IOException {
* @since 12
*/
public void skipNBytes(long n) throws IOException {
if (n > 0) {
while (n > 0) {
long ns = skip(n);
if (ns >= 0 && ns < n) { // skipped too few bytes
if (ns > 0 && ns <= n) {
// adjust number to skip
n -= ns;
// read until requested number skipped or EOS reached
while (n > 0 && read() != -1) {
n--;
}
// if not enough skipped, then EOFE
if (n != 0) {
} else if (ns == 0) { // no bytes skipped
// read one byte to check for EOS
if (read() == -1) {
throw new EOFException();
}
} else if (ns != n) { // skipped negative or too many bytes
// one byte read so decrement number to skip
n--;
} else { // skipped negative or too many bytes
throw new IOException("Unable to skip exactly");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1717,7 +1717,7 @@ private void putStringAt(int index, String str, int off, int end) {
if (getCoder() != str.coder()) {
inflate();
}
str.getBytes(value, off, index, coder, end);
str.getBytes(value, off, index, coder, end - off);
}

private void putStringAt(int index, String str) {
Expand Down
3 changes: 3 additions & 0 deletions src/java.base/share/classes/java/lang/System.java
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,9 @@ public void addReads(Module m1, Module m2) {
public void addReadsAllUnnamed(Module m) {
m.implAddReadsAllUnnamed();
}
public void addExports(Module m, String pn) {
m.implAddExports(pn);
}
public void addExports(Module m, String pn, Module other) {
m.implAddExports(pn, other);
}
Expand Down
14 changes: 10 additions & 4 deletions src/java.base/share/classes/java/lang/module/Resolver.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -560,7 +560,7 @@ private Map<ResolvedModule, Set<ResolvedModule>> makeGraph(Configuration cf) {
for (ModuleDescriptor.Requires requires : descriptor.requires()) {
String dn = requires.name();

ResolvedModule m2 = null;
ResolvedModule m2;
ModuleReference mref2 = nameToReference.get(dn);
if (mref2 != null) {
// same configuration
Expand All @@ -572,6 +572,14 @@ private Map<ResolvedModule, Set<ResolvedModule>> makeGraph(Configuration cf) {
assert requires.modifiers().contains(Modifier.STATIC);
continue;
}

// m2 is automatic module in parent configuration => m1 reads
// all automatic modules that m2 reads.
if (m2.descriptor().isAutomatic()) {
m2.reads().stream()
.filter(d -> d.descriptor().isAutomatic())
.forEach(reads::add);
}
}

// m1 requires m2 => m1 reads m2
Expand Down Expand Up @@ -838,9 +846,7 @@ private ResolvedModule findInParent(String mn) {
* Invokes the beforeFinder to find method to find the given module.
*/
private ModuleReference findWithBeforeFinder(String mn) {

return beforeFinder.find(mn).orElse(null);

}

/**
Expand Down
201 changes: 200 additions & 1 deletion src/java.base/share/classes/java/lang/reflect/InvocationHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -25,6 +25,12 @@

package java.lang.reflect;

import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;

import java.lang.invoke.MethodHandle;
import java.util.Objects;

/**
* {@code InvocationHandler} is the interface implemented by
* the <i>invocation handler</i> of a proxy instance.
Expand Down Expand Up @@ -92,4 +98,197 @@ public interface InvocationHandler {
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;

/**
* Invokes the specified default method on the given {@code proxy} instance with
* the given parameters. The given {@code method} must be a default method
* declared in a proxy interface of the {@code proxy}'s class or inherited
* from its superinterface directly or indirectly.
* <p>
* Invoking this method behaves as if {@code invokespecial} instruction executed
* from the proxy class, targeting the default method in a proxy interface.
* This is equivalent to the invocation:
* {@code X.super.m(A* a)} where {@code X} is a proxy interface and the call to
* {@code X.super::m(A*)} is resolved to the given {@code method}.
* <p>
* Examples: interface {@code A} and {@code B} both declare a default
* implementation of method {@code m}. Interface {@code C} extends {@code A}
* and inherits the default method {@code m} from its superinterface {@code A}.
*
* <blockquote><pre>{@code
* interface A {
* default T m(A a) { return t1; }
* }
* interface B {
* default T m(A a) { return t2; }
* }
* interface C extends A {}
* }</pre></blockquote>
*
* The following creates a proxy instance that implements {@code A}
* and invokes the default method {@code A::m}.
*
* <blockquote><pre>{@code
* Object proxy = Proxy.newProxyInstance(loader, new Class<?>[] { A.class },
* (o, m, params) -> {
* if (m.isDefault()) {
* // if it's a default method, invoke it
* return InvocationHandler.invokeDefault(o, m, params);
* }
* });
* }</pre></blockquote>
*
* If a proxy instance implements both {@code A} and {@code B}, both
* of which provides the default implementation of method {@code m},
* the invocation handler can dispatch the method invocation to
* {@code A::m} or {@code B::m} via the {@code invokeDefault} method.
* For example, the following code delegates the method invocation
* to {@code B::m}.
*
* <blockquote><pre>{@code
* Object proxy = Proxy.newProxyInstance(loader, new Class<?>[] { A.class, B.class },
* (o, m, params) -> {
* if (m.getName().equals("m")) {
* // invoke B::m instead of A::m
* Method bMethod = B.class.getMethod(m.getName(), m.getParameterTypes());
* return InvocationHandler.invokeDefault(o, bMethod, params);
* }
* });
* }</pre></blockquote>
*
* If a proxy instance implements {@code C} that inherits the default
* method {@code m} from its superinterface {@code A}, then
* the interface method invocation on {@code "m"} is dispatched to
* the invocation handler's {@link #invoke(Object, Method, Object[]) invoke}
* method with the {@code Method} object argument representing the
* default method {@code A::m}.
*
* <blockquote><pre>{@code
* Object proxy = Proxy.newProxyInstance(loader, new Class<?>[] { C.class },
* (o, m, params) -> {
* if (m.isDefault()) {
* // behaves as if calling C.super.m(params)
* return InvocationHandler.invokeDefault(o, m, params);
* }
* });
* }</pre></blockquote>
*
* The invocation of method {@code "m"} on this {@code proxy} will behave
* as if {@code C.super::m} is called and that is resolved to invoking
* {@code A::m}.
* <p>
* Adding a default method, or changing a method from abstract to default
* may cause an exception if an existing code attempts to call {@code invokeDefault}
* to invoke a default method.
*
* For example, if {@code C} is modified to implement a default method
* {@code m}:
*
* <blockquote><pre>{@code
* interface C extends A {
* default T m(A a) { return t3; }
* }
* }</pre></blockquote>
*
* The code above that creates proxy instance {@code proxy} with
* the modified {@code C} will run with no exception and it will result in
* calling {@code C::m} instead of {@code A::m}.
* <p>
* The following is another example that creates a proxy instance of {@code C}
* and the invocation handler calls the {@code invokeDefault} method
* to invoke {@code A::m}:
*
* <blockquote><pre>{@code
* C c = (C) Proxy.newProxyInstance(loader, new Class<?>[] { C.class },
* (o, m, params) -> {
* if (m.getName().equals("m")) {
* // IllegalArgumentException thrown as {@code A::m} is not a method
* // inherited from its proxy interface C
* Method aMethod = A.class.getMethod(m.getName(), m.getParameterTypes());
* return InvocationHandler.invokeDefault(o, aMethod params);
* }
* });
* c.m(...);
* }</pre></blockquote>
*
* The above code runs successfully with the old version of {@code C} and
* {@code A::m} is invoked. When running with the new version of {@code C},
* the above code will fail with {@code IllegalArgumentException} because
* {@code C} overrides the implementation of the same method and
* {@code A::m} is not accessible by a proxy instance.
*
* @apiNote
* The {@code proxy} parameter is of type {@code Object} rather than {@code Proxy}
* to make it easy for {@link InvocationHandler#invoke(Object, Method, Object[])
* InvocationHandler::invoke} implementation to call directly without the need
* of casting.
*
* @param proxy the {@code Proxy} instance on which the default method to be invoked
* @param method the {@code Method} instance corresponding to a default method
* declared in a proxy interface of the proxy class or inherited
* from its superinterface directly or indirectly
* @param args the parameters used for the method invocation; can be {@code null}
* if the number of formal parameters required by the method is zero.
* @return the value returned from the method invocation
*
* @throws IllegalArgumentException if any of the following conditions is {@code true}:
* <ul>
* <li>{@code proxy} is not {@linkplain Proxy#isProxyClass(Class)
* a proxy instance}; or</li>
* <li>the given {@code method} is not a default method declared
* in a proxy interface of the proxy class and not inherited from
* any of its superinterfaces; or</li>
* <li>the given {@code method} is overridden directly or indirectly by
* the proxy interfaces and the method reference to the named
* method never resolves to the given {@code method}; or</li>
* <li>the length of the given {@code args} array does not match the
* number of parameters of the method to be invoked; or</li>
* <li>any of the {@code args} elements fails the unboxing
* conversion if the corresponding method parameter type is
* a primitive type; or if, after possible unboxing, any of the
* {@code args} elements cannot be assigned to the corresponding
* method parameter type.</li>
* </ul>
* @throws IllegalAccessException if the declaring class of the specified
* default method is inaccessible to the caller class
* @throws NullPointerException if {@code proxy} or {@code method} is {@code null}
* @throws Throwable anything thrown by the default method
* @since 16
* @jvms 5.4.3. Method Resolution
*/
@CallerSensitive
public static Object invokeDefault(Object proxy, Method method, Object... args)
throws Throwable {
Objects.requireNonNull(proxy);
Objects.requireNonNull(method);

// verify that the object is actually a proxy instance
if (!Proxy.isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("'proxy' is not a proxy instance");
}
if (!method.isDefault()) {
throw new IllegalArgumentException("\"" + method + "\" is not a default method");
}
@SuppressWarnings("unchecked")
Class<? extends Proxy> proxyClass = (Class<? extends Proxy>)proxy.getClass();

Class<?> intf = method.getDeclaringClass();
// access check on the default method
method.checkAccess(Reflection.getCallerClass(), intf, proxyClass, method.getModifiers());

MethodHandle mh = Proxy.defaultMethodHandle(proxyClass, method);
// invoke the super method
try {
// the args array can be null if the number of formal parameters required by
// the method is zero (consistent with Method::invoke)
Object[] params = args != null ? args : Proxy.EMPTY_ARGS;
return mh.invokeExact(proxy, params);
} catch (ClassCastException | NullPointerException e) {
throw new IllegalArgumentException(e.getMessage(), e);
} catch (Proxy.InvocationException e) {
// unwrap and throw the exception thrown by the default method
throw e.getCause();
}
}
}
3 changes: 3 additions & 0 deletions src/java.base/share/classes/java/lang/reflect/Method.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import jdk.internal.reflect.Reflection;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.IntrinsicCandidate;
import jdk.internal.vm.annotation.Stable;
import sun.reflect.annotation.ExceptionProxy;
import sun.reflect.annotation.TypeNotPresentExceptionProxy;
import sun.reflect.generics.repository.MethodRepository;
Expand Down Expand Up @@ -66,6 +67,7 @@
* @since 1.1
*/
public final class Method extends Executable {
@Stable
private Class<?> clazz;
private int slot;
// This is guaranteed to be interned by the VM in the 1.4
Expand All @@ -74,6 +76,7 @@ public final class Method extends Executable {
private Class<?> returnType;
private Class<?>[] parameterTypes;
private Class<?>[] exceptionTypes;
@Stable
private int modifiers;
// Generics and annotations support
private transient String signature;
Expand Down
Loading

0 comments on commit f702105

Please sign in to comment.