1 /*
2 * Copyright (c) 2021, 2023, 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 jdk.tools.jlink.internal.plugins;
26
27 import java.io.IOException;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.util.*;
31
32 import jdk.internal.util.Architecture;
33 import jdk.internal.util.OperatingSystem;
34 import jdk.tools.jlink.internal.ExecutableImage;
35 import jdk.tools.jlink.internal.Platform;
36 import jdk.tools.jlink.internal.PostProcessor;
37 import jdk.tools.jlink.plugin.PluginException;
38 import jdk.tools.jlink.plugin.ResourcePool;
39 import jdk.tools.jlink.plugin.ResourcePoolBuilder;
40
41 /**
42 *
43 * CDS plugin
44 */
45 public final class CDSPlugin extends AbstractPlugin implements PostProcessor {
46 private static final String NAME = "generate-cds-archive";
47 private Platform targetPlatform;
48 private Platform runtimePlatform;
49
50 public CDSPlugin() {
51 super(NAME);
52 }
53
54
55 private String javaExecutableName() {
56 if (targetPlatform.os() == OperatingSystem.WINDOWS) {
57 return "java.exe";
58 } else {
59 return "java";
60 }
61 }
62
63 private void generateCDSArchive(ExecutableImage image, boolean noCoops) {
64 List<String> javaCmd = new ArrayList<String>();
65 Path javaPath = image.getHome().resolve("bin").resolve(javaExecutableName());
66 if (!Files.exists(javaPath)) {
67 throw new PluginException("Cannot find java executable at: " + javaPath.toString());
68 }
69 javaCmd.add(javaPath.toString());
70 javaCmd.add("-Xshare:dump");
71 String archiveMsg = "CDS";
72 if (noCoops) {
73 javaCmd.add("-XX:-UseCompressedOops");
74 archiveMsg += "-NOCOOPS";
75 }
76 ProcessBuilder builder = new ProcessBuilder(javaCmd);
77 int status = -1;
78 try {
79 Process p = builder.inheritIO().start();
80 status = p.waitFor();
81 } catch (InterruptedException | IOException e) {
82 throw new PluginException(e);
83 }
84
85 if (status != 0) {
86 throw new PluginException("Failed creating " + archiveMsg + " archive!");
87 }
88 }
89
90 @Override
91 public List<String> process(ExecutableImage image) {
92 targetPlatform = image.getTargetPlatform();
93 runtimePlatform = Platform.runtime();
94
95 if (!targetPlatform.equals(runtimePlatform)) {
96 throw new PluginException("Cannot generate CDS archives: target image platform " +
97 targetPlatform.toString() + " is different from runtime platform " +
98 runtimePlatform.toString());
99 }
100
101 Path classListPath = image.getHome().resolve("lib").resolve("classlist");
102 if (Files.exists(classListPath)) {
103 generateCDSArchive(image,false);
104
105 // The targetPlatform is the same as the runtimePlatform.
106 // For a 64-bit platform, generate the non-compressed oop CDS archive
107 if (Architecture.is64bit()) {
108 generateCDSArchive(image,true);
109 }
110 System.out.println("Created CDS archive successfully");
111 } else {
112 throw new PluginException("Cannot generate CDS archives: classlist not found: " +
113 classListPath.toString());
114 }
115 return null;
116 }
117
118 @Override
119 public Category getType() {
120 return Category.PROCESSOR;
121 }
122
123 @Override
124 public ResourcePool transform(ResourcePool in, ResourcePoolBuilder out) {
125 return in;
126 }
127 }