Skip to content

Commit

Permalink
Merge pull request #4617 from BisonSchweizAG/functionOutOfMemory
Browse files Browse the repository at this point in the history
[4.x.x] Prevent OutOfMemory on JDK 17 when loading EXPath Modules
  • Loading branch information
adamretter authored Nov 21, 2022
2 parents 9d01abf + 1c110f4 commit 47ccec2
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 54 deletions.
29 changes: 5 additions & 24 deletions exist-core/src/main/java/org/exist/repo/ExistRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,14 @@
package org.exist.repo;

import java.io.IOException;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;

Expand All @@ -44,8 +40,6 @@
import org.expath.pkg.repo.Repository;
import org.expath.pkg.repo.URISpace;

import static java.lang.invoke.MethodType.methodType;

/**
* A repository as viewed by eXist.
*
Expand All @@ -57,7 +51,6 @@
public class ExistRepository extends Observable implements BrokerPoolService {

private final static Logger LOG = LogManager.getLogger(ExistRepository.class);
private final static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
public final static String EXPATH_REPO_DIR = "expathrepo";
public final static String EXPATH_REPO_DEFAULT = "webapp/WEB-INF/" + EXPATH_REPO_DIR;

Expand Down Expand Up @@ -153,33 +146,21 @@ private Module instantiateModule(final Class<Module> clazz) throws XPathExceptio
try {
try {
// attempt for a constructor that takes 1 argument
final MethodHandle methodHandle = LOOKUP.findConstructor(clazz, methodType(void.class, Map.class));
final Function<Map, Module> ctor = (Function<Map, Module>)
LambdaMetafactory.metafactory(
LOOKUP, "apply", methodType(Function.class),
methodHandle.type().erase(), methodHandle, methodHandle.type()).getTarget().invokeExact();
return ctor.apply(Collections.emptyMap());
final Constructor<Module> cstr1 = clazz.getConstructor(Map.class);
return cstr1.newInstance(Collections.emptyMap());

} catch (final NoSuchMethodException nsme) {
// attempt for a constructor that takes 0 arguments
final MethodHandle methodHandle = LOOKUP.findConstructor(clazz, methodType(void.class, Map.class));
final Supplier<Module> ctor = (Supplier<Module>)
LambdaMetafactory.metafactory(
LOOKUP, "apply", methodType(Supplier.class),
methodHandle.type().erase(), methodHandle, methodHandle.type()).getTarget().invokeExact();
return ctor.get();
return clazz.newInstance();
}
} catch (final NoSuchMethodException nsme) {
throw new XPathException("Cannot find suitable constructor " +
"for module from EXPath repository: " + clazz.getName(), nsme);
} catch (final Throwable e) {
if (e instanceof InterruptedException) {
// NOTE: must set interrupted flag
Thread.currentThread().interrupt();
}

throw new XPathException("Unable to instantiate module from EXPath" +
"repository: " + clazz.getName());
"repository: " + clazz.getName(), e);
}
}

Expand Down
24 changes: 5 additions & 19 deletions exist-core/src/main/java/org/exist/xquery/Function.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@
*/
package org.exist.xquery;

import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.util.List;

import org.exist.dom.QName;
Expand All @@ -34,8 +32,6 @@
import org.exist.xquery.value.SequenceType;
import org.exist.xquery.value.Type;

import static java.lang.invoke.MethodType.methodType;

/**
* Abstract base class for all built-in and user-defined functions.
* <p>
Expand All @@ -52,8 +48,6 @@
*/
public abstract class Function extends PathExpr {

private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();

// Declare it in Namespaces instead? /ljo
public final static String BUILTIN_FUNCTION_NS =
"http://www.w3.org/2005/xpath-functions";
Expand Down Expand Up @@ -135,22 +129,14 @@ public static Function createFunction(final XQueryContext context, final XQueryA
Function function = null;
try {
// attempt for a constructor that takes 1 argument
final MethodHandle methodHandle = LOOKUP.findConstructor(fclazz, methodType(void.class, XQueryContext.class));
final java.util.function.Function<XQueryContext, Function> ctor = (java.util.function.Function<XQueryContext, Function>)
LambdaMetafactory.metafactory(
LOOKUP, "apply", methodType(java.util.function.Function.class),
methodHandle.type().erase(), methodHandle, methodHandle.type()).getTarget().invokeExact();
function = ctor.apply(context);
final Constructor<? extends Function> cstr1 = fclazz.getConstructor(XQueryContext.class);
function = cstr1.newInstance(context);

} catch (final NoSuchMethodException nsme1) {
try {
// attempt for a constructor that takes 2 arguments
final MethodHandle methodHandle = LOOKUP.findConstructor(fclazz, methodType(void.class, XQueryContext.class, FunctionSignature.class));
final java.util.function.BiFunction<XQueryContext, FunctionSignature, Function> ctor = (java.util.function.BiFunction<XQueryContext, FunctionSignature, Function>)
LambdaMetafactory.metafactory(
LOOKUP, "apply", methodType(java.util.function.BiFunction.class),
methodHandle.type().erase(), methodHandle, methodHandle.type()).getTarget().invokeExact();
function = ctor.apply(context, def.getSignature());
final Constructor<? extends Function> cstr2 = fclazz.getConstructor(XQueryContext.class, FunctionSignature.class);
function = cstr2.newInstance(context, def.getSignature());
} catch (final NoSuchMethodException nsme2) {
throw new XPathException(ast.getLine(), ast.getColumn(), "Constructor not found");
}
Expand Down
22 changes: 11 additions & 11 deletions exist-core/src/main/java/org/exist/xquery/XQueryContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@

import java.io.IOException;
import java.io.Reader;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
Expand Down Expand Up @@ -93,7 +91,7 @@
import org.exist.xquery.value.*;
import org.w3c.dom.Node;

import static java.lang.invoke.MethodType.methodType;
import static com.evolvedbinary.j8fu.tuple.Tuple.Tuple;
import static javax.xml.XMLConstants.XMLNS_ATTRIBUTE;
import static javax.xml.XMLConstants.XML_NS_PREFIX;
import static org.exist.Namespaces.XML_NS;
Expand Down Expand Up @@ -1472,13 +1470,15 @@ private Module instantiateModule(final String namespaceURI, final Class<Module>
final Map<String, Map<String, List<? extends Object>>> moduleParameters) {
Module module = null;
try {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
final MethodHandle methodHandle = lookup.findConstructor(mClazz, methodType(void.class, Map.class));
final java.util.function.Function<Map, Module> ctor = (java.util.function.Function<Map, Module>)
LambdaMetafactory.metafactory(
lookup, "apply", methodType(java.util.function.Function.class),
methodHandle.type().erase(), methodHandle, methodHandle.type()).getTarget().invokeExact();
module = ctor.apply(moduleParameters.get(namespaceURI));
try {
// attempt for a constructor that takes 1 argument
final Constructor<Module> cstr1 = mClazz.getConstructor(Map.class);
module = cstr1.newInstance(moduleParameters.get(namespaceURI));

} catch (final NoSuchMethodException nsme) {
// attempt for a constructor that takes 0 arguments
module = mClazz.newInstance();
}

if (namespaceURI != null && !module.getNamespaceURI().equals(namespaceURI)) {
LOG.warn("the module declares a different namespace URI. Expected: " + namespaceURI + " found: " + module.getNamespaceURI());
Expand Down

0 comments on commit 47ccec2

Please sign in to comment.