Skip to content
This repository was archived by the owner on May 28, 2018. It is now read-only.

Commit fab1516

Browse files
author
Michal Gajdos
committed
OWLS-19790: Too many open files on server startup
- Fix + tests. Updated Surefire plugin to 2.18.1 (2.17 -> 2.18.1) Updated JMockit to 1.17 (1.14 -> 1.17) Change-Id: Ic32a160167a91b25fa9272e802b560736fa4f40f Signed-off-by: Michal Gajdos <[email protected]>
1 parent f77628b commit fab1516

File tree

21 files changed

+428
-171
lines changed

21 files changed

+428
-171
lines changed

containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebAppResourcesScanner.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,23 +51,23 @@
5151
import org.glassfish.jersey.server.internal.AbstractResourceFinderAdapter;
5252
import org.glassfish.jersey.server.internal.scanning.JarFileScanner;
5353
import org.glassfish.jersey.server.internal.scanning.ResourceFinderException;
54-
import org.glassfish.jersey.server.internal.scanning.ResourceFinderStack;
54+
import org.glassfish.jersey.server.internal.scanning.CompositeResourceFinder;
5555

5656
/**
5757
* A scanner that recursively scans resources within a Web application.
5858
*
5959
* @author Paul Sandoz
6060
*/
61-
class WebAppResourcesScanner extends AbstractResourceFinderAdapter {
61+
final class WebAppResourcesScanner extends AbstractResourceFinderAdapter {
62+
63+
private static final String[] paths = new String[] {"/WEB-INF/lib/", "/WEB-INF/classes/"};
6264

63-
// private final String[] paths;
6465
private final ServletContext sc;
65-
private ResourceFinderStack resourceFinderStack = new ResourceFinderStack();
66-
private static String[] paths = new String[]{"/WEB-INF/lib/", "/WEB-INF/classes/"};
66+
private CompositeResourceFinder compositeResourceFinder = new CompositeResourceFinder();
6767

6868
/**
6969
* Scan from a set of web resource paths.
70-
* <p>
70+
* <p/>
7171
*
7272
* @param sc {@link ServletContext}.
7373
*/
@@ -77,26 +77,27 @@ class WebAppResourcesScanner extends AbstractResourceFinderAdapter {
7777
processPaths(paths);
7878
}
7979

80-
private void processPaths(String... paths) {
80+
private void processPaths(final String... paths) {
8181
for (final String path : paths) {
8282

8383
final Set<String> resourcePaths = sc.getResourcePaths(path);
8484
if (resourcePaths == null) {
8585
break;
8686
}
8787

88-
resourceFinderStack.push(new AbstractResourceFinderAdapter() {
88+
compositeResourceFinder.push(new AbstractResourceFinderAdapter() {
8989

90-
private Deque<String> resourcePathsStack = new LinkedList<String>() {
90+
private final Deque<String> resourcePathsStack = new LinkedList<String>() {
9191

9292
private static final long serialVersionUID = 3109256773218160485L;
9393

9494
{
95-
for (String resourcePath : resourcePaths) {
95+
for (final String resourcePath : resourcePaths) {
9696
push(resourcePath);
9797
}
9898
}
9999
};
100+
100101
private String current;
101102
private String next;
102103

@@ -110,8 +111,8 @@ public boolean hasNext() {
110111
next = null;
111112
} else if (next.endsWith(".jar")) {
112113
try {
113-
resourceFinderStack.push(new JarFileScanner(sc.getResourceAsStream(next), "", true));
114-
} catch (IOException ioe) {
114+
compositeResourceFinder.push(new JarFileScanner(sc.getResourceAsStream(next), "", true));
115+
} catch (final IOException ioe) {
115116
throw new ResourceFinderException(ioe);
116117
}
117118
next = null;
@@ -148,22 +149,27 @@ public void reset() {
148149

149150
@Override
150151
public boolean hasNext() {
151-
return resourceFinderStack.hasNext();
152+
return compositeResourceFinder.hasNext();
152153
}
153154

154155
@Override
155156
public String next() {
156-
return resourceFinderStack.next();
157+
return compositeResourceFinder.next();
157158
}
158159

159160
@Override
160161
public InputStream open() {
161-
return resourceFinderStack.open();
162+
return compositeResourceFinder.open();
163+
}
164+
165+
@Override
166+
public void close() {
167+
compositeResourceFinder.close();
162168
}
163169

164170
@Override
165171
public void reset() {
166-
resourceFinderStack = new ResourceFinderStack();
172+
compositeResourceFinder = new CompositeResourceFinder();
167173
processPaths(paths);
168174
}
169175
}

core-server/pom.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,11 @@
155155
<configuration>
156156
<argLine>${surefire.security.argline}</argLine>
157157
<!-- Execute test classes in parallel - 1 thread per CPU core. -->
158-
<parallel>classesAndMethods</parallel>
158+
<parallel>classes</parallel>
159159
<perCoreThreadCount>true</perCoreThreadCount>
160160
<threadCount>1</threadCount>
161+
<forkCount>1C</forkCount>
162+
<reuseForks>true</reuseForks>
161163
</configuration>
162164
</plugin>
163165
</plugins>
@@ -222,6 +224,11 @@
222224
<scope>provided</scope>
223225
</dependency>
224226

227+
<dependency>
228+
<groupId>org.jmockit</groupId>
229+
<artifactId>jmockit</artifactId>
230+
<scope>test</scope>
231+
</dependency>
225232
<dependency>
226233
<groupId>junit</groupId>
227234
<artifactId>junit</artifactId>

core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ public class ResourceConfig extends Application implements Configurable<Resource
9595
private transient Set<Object> cachedSingletons = null;
9696
private transient Set<Object> cachedSingletonsView = null;
9797

98+
private transient boolean resetFinders = false;
99+
98100
private volatile State state;
99101

100102
private static class State extends CommonConfig implements ServerConfig {
@@ -609,6 +611,7 @@ public final ResourceConfig registerFinder(final ResourceFinder resourceFinder)
609611
if (resourceFinder == null) {
610612
return this;
611613
}
614+
invalidateCache();
612615

613616
this.state.registerFinder(resourceFinder);
614617
return this;
@@ -708,8 +711,11 @@ final void invalidateCache() {
708711
this.cachedSingletonsView = null;
709712

710713
// Reset ResourceFinders to make sure the next package scanning is successful.
711-
for (final ResourceFinder finder : this.state.resourceFinders) {
712-
finder.reset();
714+
if (resetFinders) {
715+
for (final ResourceFinder finder : this.state.resourceFinders) {
716+
finder.reset();
717+
}
718+
resetFinders = false;
713719
}
714720
}
715721

@@ -864,6 +870,9 @@ private Set<Class<?>> scanClasses() {
864870
final ResourceConfig.State _state = state;
865871
final Set<ResourceFinder> rfs = Sets.newHashSet(_state.getResourceFinders());
866872

873+
// In case new entity is registered the available finders should be reset.
874+
resetFinders = true;
875+
867876
// classes registered via configuration property
868877
final String[] classNames = parsePropertyValue(ServerProperties.PROVIDER_CLASSNAMES);
869878
if (classNames != null) {

core-server/src/main/java/org/glassfish/jersey/server/ResourceFinder.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33
*
4-
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
4+
* Copyright (c) 2012-2015 Oracle and/or its affiliates. All rights reserved.
55
*
66
* The contents of this file are subject to the terms of either the GNU
77
* General Public License Version 2 only ("GPL") or the Common Development
@@ -44,31 +44,45 @@
4444

4545
/**
4646
* An interface used for finding and opening (loading) new resources.
47-
*
47+
* <p/>
4848
* {@link ResourceConfig} will use all registered finders to obtain classes
4949
* to be used as resource classes and/or providers. Method {@link #open()} doesn't
5050
* need to be called on all returned resource names, {@link ResourceConfig} can ignore
5151
* some of them.
52-
*
52+
* <p/>
5353
* Currently, all resource names ending with ".class" will be accepted and processed (opened).
54+
* <p/>
55+
* Extends {@link AutoCloseable} since version 2.19. The {@link #close()} method is used to release
56+
* allocated/opened resources (such as streams). When a resource finder is closed no other method should be
57+
* invoked on it.
5458
*
5559
* @author Pavel Bucek (pavel.bucek at oracle.com)
5660
*/
57-
public interface ResourceFinder extends Iterator<String> {
61+
public interface ResourceFinder extends Iterator<String>, AutoCloseable {
5862

5963
/**
6064
* Open current resource.
6165
*
6266
* @return input stream from which current resource can be loaded.
6367
*/
64-
InputStream open();
68+
public InputStream open();
69+
70+
/**
71+
* {@inheritDoc}
72+
* <p/>
73+
* Release allocated/opened resources (such as streams). When the resource finder is closed
74+
* no other method should be invoked on it.
75+
*
76+
* @since 2.19
77+
*/
78+
public void close();
6579

6680
/**
6781
* Reset the {@link ResourceFinder} instance.
6882
* <p/>
6983
* Upon calling this method the implementing class MUST reset its internal state to the initial state.
7084
*/
71-
void reset();
85+
public void reset();
7286

7387
/**
7488
* {@inheritDoc}
@@ -77,5 +91,5 @@ public interface ResourceFinder extends Iterator<String> {
7791
* when invoked.
7892
*/
7993
@Override
80-
void remove();
94+
public void remove();
8195
}

core-server/src/main/java/org/glassfish/jersey/server/internal/AbstractResourceFinderAdapter.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,18 @@
5050
public abstract class AbstractResourceFinderAdapter implements ResourceFinder {
5151

5252
/**
53-
* Default implementation of {@link #remove()} which complies with the defined contract.
53+
* Default implementation of {@code #remove()} which complies with the defined contract.
5454
*/
5555
@Override
5656
public void remove() {
5757
throw new UnsupportedOperationException();
5858
}
59+
60+
/**
61+
* Default implementation of {@code #close()} which does nothing.
62+
*/
63+
@Override
64+
public void close() {
65+
// NO-OP.
66+
}
5967
}

core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/BundleSchemeResourceFinderFactory.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@
4242
import java.io.IOException;
4343
import java.io.InputStream;
4444
import java.net.URI;
45-
import java.util.Arrays;
46-
import java.util.HashSet;
45+
import java.util.Collections;
4746
import java.util.NoSuchElementException;
4847
import java.util.Set;
4948

@@ -54,11 +53,13 @@
5453
*
5554
* @author Jakub Podlesak (jakub.podlesak at oracle.com)
5655
*/
57-
class BundleSchemeResourceFinderFactory implements UriSchemeResourceFinderFactory {
56+
final class BundleSchemeResourceFinderFactory implements UriSchemeResourceFinderFactory {
57+
58+
private static final Set<String> SCHEMES = Collections.singleton("bundle");
5859

5960
@Override
6061
public Set<String> getSchemes() {
61-
return new HashSet<>(Arrays.asList("bundle"));
62+
return SCHEMES;
6263
}
6364

6465
/**
@@ -68,17 +69,17 @@ public Set<String> getSchemes() {
6869
}
6970

7071
@Override
71-
public BundleSchemeScanner create(URI uri, boolean recursive) {
72+
public BundleSchemeScanner create(final URI uri, final boolean recursive) {
7273
return new BundleSchemeScanner(uri);
7374
}
7475

7576
private class BundleSchemeScanner extends AbstractResourceFinderAdapter {
7677

77-
private BundleSchemeScanner(URI uri) {
78+
private BundleSchemeScanner(final URI uri) {
7879
this.uri = uri;
7980
}
8081

81-
private URI uri;
82+
private final URI uri;
8283

8384
/**
8485
* Marks this iterator as iterated after execution of {@link #open()} method.
@@ -113,7 +114,7 @@ public InputStream open() {
113114
try {
114115
accessed = true;
115116
return uri.toURL().openStream();
116-
} catch (IOException e) {
117+
} catch (final IOException e) {
117118
throw new ResourceFinderException(e);
118119
}
119120
}
Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,25 @@
4444
import java.util.LinkedList;
4545
import java.util.NoSuchElementException;
4646
import java.util.Stack;
47+
import java.util.logging.Level;
48+
import java.util.logging.Logger;
4749

48-
import org.glassfish.jersey.server.internal.AbstractResourceFinderAdapter;
4950
import org.glassfish.jersey.server.ResourceFinder;
51+
import org.glassfish.jersey.server.internal.AbstractResourceFinderAdapter;
52+
import org.glassfish.jersey.server.internal.LocalizationMessages;
5053

5154
/**
5255
* {@link Stack} of {@link ResourceFinder} instances.
53-
*
56+
* <p/>
5457
* Used to combine various finders into one instance.
5558
*
5659
* @author Pavel Bucek (pavel.bucek at oracle.com)
5760
*/
58-
public class ResourceFinderStack extends AbstractResourceFinderAdapter {
61+
public final class CompositeResourceFinder extends AbstractResourceFinderAdapter {
5962

60-
private final Deque<ResourceFinder> stack = new LinkedList<ResourceFinder>();
63+
private static final Logger LOGGER = Logger.getLogger(CompositeResourceFinder.class.getName());
64+
65+
private final Deque<ResourceFinder> stack = new LinkedList<>();
6166
private ResourceFinder current = null;
6267

6368
@Override
@@ -96,12 +101,29 @@ public InputStream open() {
96101
return current.open();
97102
}
98103

99-
public void push(ResourceFinder iterator) {
100-
stack.push(iterator);
104+
@Override
105+
public void close() {
106+
if (current != null) {
107+
// Insert the currently processed resource finder at the top of the stack.
108+
stack.addFirst(current);
109+
current = null;
110+
}
111+
for (final ResourceFinder finder : stack) {
112+
try {
113+
finder.close();
114+
} catch (final RuntimeException e) {
115+
LOGGER.log(Level.CONFIG, LocalizationMessages.ERROR_CLOSING_FINDER(finder.getClass()), e);
116+
}
117+
}
118+
stack.clear();
101119
}
102120

103121
@Override
104122
public void reset() {
105123
throw new UnsupportedOperationException();
106124
}
125+
126+
public void push(final ResourceFinder iterator) {
127+
stack.push(iterator);
128+
}
107129
}

0 commit comments

Comments
 (0)