Skip to content

Commit c660014

Browse files
author
Christian Wimmer
committed
Avoid pulling File and URL code in image via CodeSource.location
1 parent 4175303 commit c660014

File tree

3 files changed

+123
-29
lines changed

3 files changed

+123
-29
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
//Checkstyle: allow reflection
2828

29-
import java.io.File;
3029
import java.io.InputStream;
3130
import java.io.Serializable;
3231
import java.lang.annotation.Annotation;
@@ -43,11 +42,8 @@
4342
import java.lang.reflect.Modifier;
4443
import java.lang.reflect.Type;
4544
import java.lang.reflect.TypeVariable;
46-
import java.net.MalformedURLException;
4745
import java.net.URL;
48-
import java.security.CodeSource;
4946
import java.security.ProtectionDomain;
50-
import java.security.cert.Certificate;
5147
import java.util.List;
5248
import java.util.Optional;
5349
import java.util.Set;
@@ -58,7 +54,6 @@
5854
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
5955
import org.graalvm.nativeimage.Platform;
6056
import org.graalvm.nativeimage.Platforms;
61-
import org.graalvm.nativeimage.ProcessProperties;
6257
import org.graalvm.nativeimage.c.function.CFunctionPointer;
6358
import org.graalvm.util.DirectAnnotationAccess;
6459

@@ -89,7 +84,6 @@
8984
import com.oracle.svm.util.ReflectionUtil.ReflectionUtilError;
9085

9186
import jdk.vm.ci.meta.JavaKind;
92-
import sun.security.util.SecurityConstants;
9387

9488
@Hybrid(canHybridFieldsBeDuplicated = false)
9589
@Substitute
@@ -318,28 +312,6 @@ public void setModule(Object module) {
318312
this.module = module;
319313
}
320314

321-
/**
322-
* Final fields in subsituted classes are treated as implicitly RecomputeFieldValue even when
323-
* not annotated with @RecomputeFieldValue. Their name must not match a field in the original
324-
* class, i.e., allPermDomain.
325-
*/
326-
static final LazyFinalReference<java.security.ProtectionDomain> allPermDomainReference = new LazyFinalReference<>(() -> {
327-
java.security.Permissions perms = new java.security.Permissions();
328-
perms.add(SecurityConstants.ALL_PERMISSION);
329-
CodeSource cs;
330-
try {
331-
// Try to use executable image's name as code source for the class.
332-
// The file location can be used by Java code to determine its location on disk, similar
333-
// to argv[0].
334-
cs = new CodeSource(new File(ProcessProperties.getExecutableName()).toURI().toURL(), (Certificate[]) null);
335-
} catch (MalformedURLException ex) {
336-
// This should not really happen; the file is cannonicalized, absolute, so it should
337-
// always have file:// URL.
338-
cs = null;
339-
}
340-
return new java.security.ProtectionDomain(cs, perms);
341-
});
342-
343315
private final LazyFinalReference<DynamicHubCompanion> companion = new LazyFinalReference<>(() -> new DynamicHubCompanion(this));
344316

345317
@Platforms(Platform.HOSTED_ONLY.class)

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.graalvm.nativeimage.ImageSingletons;
4242

4343
import com.oracle.svm.core.hub.DynamicHub.ReflectionData;
44+
import com.oracle.svm.core.jdk.ProtectionDomainSupport;
4445
import com.oracle.svm.core.reflect.MethodMetadataDecoder;
4546
import com.oracle.svm.core.reflect.MethodMetadataDecoder.MethodDescriptor;
4647
import com.oracle.svm.core.util.VMError;
@@ -82,7 +83,7 @@ public void setClassLoader(ClassLoader loader) {
8283

8384
public ProtectionDomain getProtectionDomain() {
8485
if (protectionDomain == null) {
85-
protectionDomain = DynamicHub.allPermDomainReference.get();
86+
protectionDomain = ProtectionDomainSupport.allPermDomain();
8687
}
8788
return protectionDomain;
8889
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.jdk;
26+
27+
// Checkstyle: allow reflection
28+
29+
import java.io.File;
30+
import java.net.MalformedURLException;
31+
import java.net.URL;
32+
import java.security.CodeSource;
33+
import java.security.ProtectionDomain;
34+
import java.security.cert.Certificate;
35+
import java.util.function.Supplier;
36+
37+
import org.graalvm.nativeimage.ImageSingletons;
38+
import org.graalvm.nativeimage.Platform;
39+
import org.graalvm.nativeimage.Platforms;
40+
import org.graalvm.nativeimage.ProcessProperties;
41+
import org.graalvm.nativeimage.hosted.Feature;
42+
43+
import com.oracle.svm.core.annotate.AutomaticFeature;
44+
import com.oracle.svm.core.util.LazyFinalReference;
45+
import com.oracle.svm.util.ReflectionUtil;
46+
47+
import sun.security.util.SecurityConstants;
48+
49+
/**
50+
* All classes that do not set a ProtectionDomain explicitly have a "default" ProtectionDomain. And
51+
* every ProtectionDomain has a CodeSource with a URL as its location.
52+
*
53+
* If an application invokes {@link CodeSource#getLocation()}, it can reasonably expect a non-null
54+
* URL. We use the executable image's name as the location, because that is the best value we can
55+
* provide.
56+
*
57+
* But computing the URL for the location pulls in a lot of JDK dependencies. For a simple
58+
* application like "Hello World", that would significantly increase the image size. So we only add
59+
* code to compute the URL if the application explicitly invokes {@link CodeSource#getLocation()}.
60+
* This is done using a reachability handler registered in
61+
* {@link ProtectionDomainFeature#beforeAnalysis}.
62+
*
63+
* Note that this still leads to observable differences in places where the location is used
64+
* implicitly, like {@link CodeSource#toString} and {@link CodeSource#implies}. We accept that
65+
* difference in behavior.
66+
*/
67+
public final class ProtectionDomainSupport {
68+
69+
private final LazyFinalReference<ProtectionDomain> allPermDomain = new LazyFinalReference<>(this::createAllPermDomain);
70+
71+
/** Remains null as long as the reachability handler has not triggered. */
72+
Supplier<URL> executableURLSupplier;
73+
74+
public static ProtectionDomain allPermDomain() {
75+
return ImageSingletons.lookup(ProtectionDomainSupport.class).allPermDomain.get();
76+
}
77+
78+
private ProtectionDomain createAllPermDomain() {
79+
java.security.Permissions perms = new java.security.Permissions();
80+
perms.add(SecurityConstants.ALL_PERMISSION);
81+
URL executableURL = executableURLSupplier != null ? executableURLSupplier.get() : null;
82+
CodeSource cs = new CodeSource(executableURL, (Certificate[]) null);
83+
return new java.security.ProtectionDomain(cs, perms);
84+
}
85+
86+
private static URL createExecutableURL() {
87+
try {
88+
/*
89+
* Try to use executable image's name as code source for the class. The file location
90+
* can be used by Java code to determine its location on disk, similar to argv[0].
91+
*/
92+
return new File(ProcessProperties.getExecutableName()).toURI().toURL();
93+
} catch (MalformedURLException ex) {
94+
/*
95+
* This should not really happen; the file is canonicalized, absolute, so it should
96+
* always have a file:// URL.
97+
*/
98+
return null;
99+
}
100+
}
101+
102+
@Platforms(Platform.HOSTED_ONLY.class)
103+
static void enableCodeSource(Feature.DuringAnalysisAccess access) {
104+
ImageSingletons.lookup(ProtectionDomainSupport.class).executableURLSupplier = ProtectionDomainSupport::createExecutableURL;
105+
access.requireAnalysisIteration();
106+
}
107+
}
108+
109+
@AutomaticFeature
110+
final class ProtectionDomainFeature implements Feature {
111+
@Override
112+
public void afterRegistration(AfterRegistrationAccess access) {
113+
ImageSingletons.add(ProtectionDomainSupport.class, new ProtectionDomainSupport());
114+
}
115+
116+
@Override
117+
public void beforeAnalysis(BeforeAnalysisAccess access) {
118+
access.registerReachabilityHandler(ProtectionDomainSupport::enableCodeSource,
119+
ReflectionUtil.lookupMethod(CodeSource.class, "getLocation"));
120+
}
121+
}

0 commit comments

Comments
 (0)