Merge pull request #3139 from sdedic/bugfix/javacompiler-phase
Get elements resolved before working with types.
diff --git a/ide/projectapi/src/org/netbeans/modules/projectapi/LazyLookup.java b/ide/projectapi/src/org/netbeans/modules/projectapi/LazyLookup.java
new file mode 100644
index 0000000..fd57a98
--- /dev/null
+++ b/ide/projectapi/src/org/netbeans/modules/projectapi/LazyLookup.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.projectapi;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.logging.Level;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+
+final class LazyLookup extends ProxyLookup {
+ private final Map<String, Object> attrs;
+ private final Lookup lkp;
+ private Collection<String> serviceNames;
+ final Thread[] LOCK = {null};
+
+ public LazyLookup(Map<String, Object> attrs, Lookup lkp) {
+ this.attrs = attrs;
+ this.lkp = lkp;
+ this.serviceNames = Arrays.asList(((String) attrs.get("service")).split(",")); // NOI18N
+ }
+
+ @Override
+ protected void beforeLookup(Template<?> template) {
+ class NotifyLater implements Executor {
+ private List<Runnable> pending = new ArrayList<>();
+ @Override
+ public void execute(Runnable command) {
+ pending.add(command);
+ }
+
+ public void deliverPending() {
+ List<Runnable> notify = pending;
+ pending = null;
+ for (Runnable r : notify) {
+ r.run();
+ }
+ }
+ }
+ LazyLookupProviders.safeToLoad(this.lkp);
+ Class<?> service = template.getType();
+ NotifyLater later = null;
+ synchronized (LOCK) {
+ for (;;) {
+ if (serviceNames == null || !serviceNames.contains(service.getName())) {
+ return;
+ }
+ if (LOCK[0] == null) {
+ break;
+ }
+ if (LOCK[0] == Thread.currentThread()) {
+ return;
+ }
+ try {
+ LOCK.wait();
+ } catch (InterruptedException ex) {
+ LazyLookupProviders.LOG.log(Level.INFO, null, ex);
+ }
+ }
+ LOCK[0] = Thread.currentThread();
+ LOCK.notifyAll();
+ }
+ try {
+ Object instance = LazyLookupProviders.loadPSPInstance((String) attrs.get("class"), (String) attrs.get("method"), lkp); // NOI18N
+ if (!service.isInstance(instance)) {
+ // JRE #6456938: Class.cast currently throws an exception without details.
+ throw new ClassCastException("Instance of " + instance.getClass() + " unassignable to " + service);
+ }
+ setLookups(later = new NotifyLater(), Lookups.singleton(instance));
+ synchronized (LOCK) {
+ serviceNames = null;
+ LOCK.notifyAll();
+ }
+ } catch (Exception x) {
+ Exceptions.attachMessage(x, "while loading from " + attrs);
+ Exceptions.printStackTrace(x);
+ } finally {
+ synchronized (LOCK) {
+ LOCK[0] = null;
+ LOCK.notifyAll();
+ }
+ if (later != null) {
+ later.deliverPending();
+ }
+ }
+ }
+
+ boolean isInitializing() {
+ return LOCK[0] != null;
+ }
+
+ @Override
+ @SuppressWarnings(value = "element-type-mismatch")
+ public String toString() {
+ return "LazyLookupProviders.LookupProvider[service=" + attrs.get("service") + ", class=" + attrs.get("class") + ", orig=" + attrs.get(FileObject.class) + "]";
+ }
+
+}
diff --git a/ide/projectapi/src/org/netbeans/modules/projectapi/LazyLookupProviders.java b/ide/projectapi/src/org/netbeans/modules/projectapi/LazyLookupProviders.java
index 6b62c69..74bfc11 100644
--- a/ide/projectapi/src/org/netbeans/modules/projectapi/LazyLookupProviders.java
+++ b/ide/projectapi/src/org/netbeans/modules/projectapi/LazyLookupProviders.java
@@ -23,7 +23,6 @@
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -37,13 +36,9 @@
import org.netbeans.spi.project.LookupMerger;
import org.netbeans.spi.project.LookupProvider;
import org.netbeans.spi.project.ProjectServiceProvider;
-import org.openide.filesystems.FileObject;
import org.openide.util.ChangeSupport;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
-import org.openide.util.Lookup.Template;
-import org.openide.util.lookup.Lookups;
-import org.openide.util.lookup.ProxyLookup;
/**
* Factory methods for lazy {@link LookupProvider} registration.
@@ -52,7 +47,7 @@
private LazyLookupProviders() {}
- private static final Logger LOG = Logger.getLogger(LazyLookupProviders.class.getName());
+ static final Logger LOG = Logger.getLogger(LazyLookupProviders.class.getName());
private static final Map<Lookup,ThreadLocal<Member>> INSIDE_LOAD = new WeakHashMap<Lookup,ThreadLocal<Member>>();
private static final Collection<Member> WARNED = Collections.synchronizedSet(new HashSet<Member>());
@@ -62,97 +57,39 @@
public static LookupProvider forProjectServiceProvider(final Map<String,Object> attrs) throws ClassNotFoundException {
class Prov implements LookupProvider {
@Override
- public Lookup createAdditionalLookup(final Lookup lkp) {
- final Lookup result = new ProxyLookup() {
- Collection<String> serviceNames = Arrays.asList(((String) attrs.get("service")).split(",")); // NOI18N
- final Thread[] LOCK = { null };
- @Override protected void beforeLookup(Template<?> template) {
- safeToLoad();
- Class<?> service = template.getType();
- synchronized (LOCK) {
- for (;;) {
- if (serviceNames == null || !serviceNames.contains(service.getName())) {
- return;
- }
- if (LOCK[0] == null) {
- break;
- }
- if (LOCK[0] == Thread.currentThread()) {
- return;
- }
- try {
- LOCK.wait();
- } catch (InterruptedException ex) {
- LOG.log(Level.INFO, null, ex);
- }
- }
- LOCK[0] = Thread.currentThread();
- }
- try {
- Object instance = loadPSPInstance((String) attrs.get("class"), (String) attrs.get("method"), lkp); // NOI18N
- if (!service.isInstance(instance)) {
- // JRE #6456938: Class.cast currently throws an exception without details.
- throw new ClassCastException("Instance of " + instance.getClass() + " unassignable to " + service);
- }
- setLookups(Lookups.singleton(instance));
- synchronized (LOCK) {
- serviceNames = null;
- }
- } catch (Exception x) {
- Exceptions.attachMessage(x, "while loading from " + attrs);
- Exceptions.printStackTrace(x);
- } finally {
- synchronized (LOCK) {
- LOCK[0] = null;
- LOCK.notifyAll();
- }
- }
- }
- private void safeToLoad() {
- ThreadLocal<Member> memberRef;
- synchronized (INSIDE_LOAD) {
- memberRef = INSIDE_LOAD.get(lkp);
- }
- if (memberRef == null) {
- return;
- }
- Member member = memberRef.get();
- if (member != null && WARNED.add(member)) {
- LOG.log(Level.WARNING, null, new IllegalStateException("may not call Project.getLookup().lookup(...) inside " + member.getName() + " registered under @ProjectServiceProvider"));
- }
- }
-
- @Override
- public String toString() {
- return Prov.this.toString();
- }
- };
+ public Lookup createAdditionalLookup(Lookup lkp) {
+ LazyLookup result = new LazyLookup(attrs, lkp);
if (LOG.isLoggable(Level.FINE)) {
LOG.log(
- Level.FINE,
- "Additional lookup created: {0} service class: {1} for base lookup: {2}", //NOI18N
- new Object[]{
+ Level.FINE,
+ "Additional lookup created: {0} service class: {1} for base lookup: {2}", //NOI18N
+ new Object[]{
System.identityHashCode(result),
- attrs.get("class"),
- System.identityHashCode(lkp)
- });
+ attrs.get("class"),
+ System.identityHashCode(lkp)
+ });
}
return result;
}
-
- @Override
- @SuppressWarnings("element-type-mismatch")
- public String toString() {
- return "LazyLookupProviders.LookupProvider[service=" +
- attrs.get("service") +
- ", class=" + attrs.get("class") +
- ", orig=" + attrs.get(FileObject.class) +
- "]";
- }
- };
+ }
return new Prov();
}
- private static Object loadPSPInstance(String implName, String methodName, Lookup lkp) throws Exception {
+
+ static void safeToLoad(Lookup lkp) {
+ ThreadLocal<Member> memberRef;
+ synchronized (LazyLookupProviders.INSIDE_LOAD) {
+ memberRef = LazyLookupProviders.INSIDE_LOAD.get(lkp);
+ }
+ if (memberRef == null) {
+ return;
+ }
+ Member member = memberRef.get();
+ if (member != null && LazyLookupProviders.WARNED.add(member)) {
+ LazyLookupProviders.LOG.log(Level.WARNING, null, new IllegalStateException("may not call Project.getLookup().lookup(...) inside " + member.getName() + " registered under @ProjectServiceProvider"));
+ }
+ }
+
+ static Object loadPSPInstance(String implName, String methodName, Lookup lkp) throws Exception {
ClassLoader loader = Lookup.getDefault().lookup(ClassLoader.class);
if (loader == null) {
loader = Thread.currentThread().getContextClassLoader();
diff --git a/ide/projectapi/src/org/netbeans/spi/project/support/DelegatingLookupImpl.java b/ide/projectapi/src/org/netbeans/spi/project/support/DelegatingLookupImpl.java
index c41a343..c3eb60c 100644
--- a/ide/projectapi/src/org/netbeans/spi/project/support/DelegatingLookupImpl.java
+++ b/ide/projectapi/src/org/netbeans/spi/project/support/DelegatingLookupImpl.java
@@ -27,6 +27,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.ChangeEvent;
@@ -47,7 +48,8 @@
private final Lookup baseLookup;
private final String pathDescriptor;
- private final UnmergedLookup unmergedLookup = new UnmergedLookup();
+ private final Controller unmergedController;
+ private final ProxyLookup unmergedLookup;
private final Map<LookupMerger<?>,Object> mergerResults = new HashMap<LookupMerger<?>,Object>();
private final Lookup.Result<LookupProvider> providerResult;
private final LookupListener providerListener;
@@ -63,6 +65,8 @@
@SuppressWarnings("LeakingThisInConstructor")
DelegatingLookupImpl(Lookup base, Lookup providerLookup, String pathDescriptor) {
assert base != null;
+ this.unmergedController = new ProxyLookup.Controller();
+ this.unmergedLookup = new ProxyLookup(this.unmergedController);
baseLookup = base;
this.pathDescriptor = pathDescriptor;
providerResult = providerLookup.lookupResult(LookupProvider.class);
@@ -96,6 +100,24 @@
}
private void doDelegate() {
+ class NotifyLater implements Executor {
+ List<Runnable> pending = new ArrayList<>();
+
+ @Override
+ public void execute(Runnable command) {
+ pending.add(command);
+ }
+
+ public void notifyCollectedEvents() {
+ List<Runnable> tmp = pending;
+ pending = null;
+ for (Runnable r : tmp) {
+ r.run();
+ }
+ }
+ }
+ NotifyLater notifyLater = new NotifyLater();
+
synchronized (results) {
for (Lookup.Result<?> r : results) {
r.removeLookupListener(this);
@@ -125,7 +147,7 @@
old = new ArrayList<LookupProvider>(providers);
currentLookups = newLookups;
newLookups.add(baseLookup);
- unmergedLookup._setLookups(newLookups.toArray(new Lookup[newLookups.size()]));
+ unmergedController.setLookups(notifyLater, newLookups.toArray(new Lookup[newLookups.size()]));
List<Class<?>> filteredClasses = new ArrayList<Class<?>>();
List<Object> mergedInstances = new ArrayList<Object>();
LookupListener l = listenerRef != null ? listenerRef.get() : null;
@@ -165,14 +187,13 @@
}
Lookup filtered = Lookups.exclude(unmergedLookup, filteredClasses.toArray(new Class<?>[filteredClasses.size()]));
Lookup fixed = Lookups.fixed(mergedInstances.toArray(new Object[mergedInstances.size()]));
- setLookups(fixed, filtered);
+ setLookups(notifyLater, fixed, filtered);
}
+ notifyLater.notifyCollectedEvents();
}
- private static class UnmergedLookup extends ProxyLookup {
- void _setLookups(Lookup... lookups) {
- setLookups(lookups);
- }
+ final boolean holdsLock() {
+ return Thread.holdsLock(results);
}
//just for assertion evaluation.
diff --git a/ide/projectapi/test/unit/src/org/netbeans/modules/projectapi/LazyLookupTest.java b/ide/projectapi/test/unit/src/org/netbeans/modules/projectapi/LazyLookupTest.java
new file mode 100644
index 0000000..3a99cb4
--- /dev/null
+++ b/ide/projectapi/test/unit/src/org/netbeans/modules/projectapi/LazyLookupTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.projectapi;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.openide.util.Lookup;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+
+public class LazyLookupTest {
+
+ public LazyLookupTest() {
+ }
+
+ @Test
+ public void testChangesAreNotifiedWithoutHoldingALock() {
+
+ Map<String,Object> data = new HashMap<>();
+ data.put("service", String.class.getName());
+ data.put("class", LazyLookupTest.class.getName());
+ data.put("method", "testFactory");
+ LazyLookup lkp = new LazyLookup(data, Lookup.EMPTY);
+
+ class LL implements LookupListener {
+ int cnt;
+
+ @Override
+ public void resultChanged(LookupEvent ev) {
+ cnt++;
+ assertFalse("Internal lock isn't held", lkp.isInitializing());
+ }
+ }
+ LL listener = new LL();
+
+ Lookup.Result<String> res = lkp.lookupResult(String.class);
+ res.addLookupListener(listener);
+
+ String value = lkp.lookup(String.class);
+ assertEquals("Hello", value);
+
+ assertEquals("One change", 1, listener.cnt);
+ }
+
+ public static String testFactory() {
+ return "Hello";
+ }
+}
diff --git a/ide/projectapi/test/unit/src/org/netbeans/spi/project/support/DelegatingLookupDeadlock5914Test.java b/ide/projectapi/test/unit/src/org/netbeans/spi/project/support/DelegatingLookupDeadlock5914Test.java
new file mode 100644
index 0000000..453d9ca
--- /dev/null
+++ b/ide/projectapi/test/unit/src/org/netbeans/spi/project/support/DelegatingLookupDeadlock5914Test.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.netbeans.spi.project.support;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JRadioButton;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import org.netbeans.junit.NbTestCase;
+import org.netbeans.spi.project.LookupMerger;
+import org.netbeans.spi.project.LookupProvider;
+import org.openide.util.Lookup;
+import org.openide.util.LookupEvent;
+import org.openide.util.LookupListener;
+import org.openide.util.lookup.AbstractLookup;
+import org.openide.util.lookup.InstanceContent;
+import org.openide.util.lookup.Lookups;
+
+public class DelegatingLookupDeadlock5914Test extends NbTestCase {
+
+ public DelegatingLookupDeadlock5914Test(String name) {
+ super(name);
+ }
+
+ public void testDontHoldLockWhenNotifyingChanges() {
+ LookupMergerImpl merger = new LookupMergerImpl();
+ Lookup base = Lookups.fixed(new JButton(), new JComboBox(), merger);
+ LookupProviderImpl pro1 = new LookupProviderImpl();
+ LookupProviderImpl pro2 = new LookupProviderImpl();
+ LookupProviderImpl pro3 = new LookupProviderImpl();
+
+ InstanceContent provInst = new InstanceContent();
+ Lookup providers = new AbstractLookup(provInst);
+ provInst.add(pro1);
+ provInst.add(pro2);
+
+ pro1.ic.add(new JTextField());
+ pro2.ic.add(new JTextArea());
+
+ DelegatingLookupImpl del = new DelegatingLookupImpl(base, providers, "<irrelevant>");
+ class LL implements LookupListener {
+ int cnt;
+
+ @Override
+ public void resultChanged(LookupEvent ev) {
+ assertFalse("Cannot hold lock when notifying changes!", del.holdsLock());
+ cnt++;
+ }
+ }
+ LL jbuttonListener = new LL();
+ Lookup.Result<JButton> jbuttonResult = del.lookupResult(JButton.class);
+ jbuttonResult.addLookupListener(jbuttonListener);
+ assertEquals("One button", 1, jbuttonResult.allInstances().size());
+
+ Lookup.Result<JRadioButton> jradioButtonResult = del.lookupResult(JRadioButton.class);
+ LL jradioButtonListener = new LL();
+ jradioButtonResult.addLookupListener(jradioButtonListener);
+ assertEquals("No radio button", 0, jradioButtonResult.allInstances().size());
+
+ assertNotNull(del.lookup(JTextArea.class));
+ assertNotNull(del.lookup(JComboBox.class));
+
+ // test merger..
+ JButton butt = del.lookup(JButton.class);
+ assertNotNull(butt);
+ assertEquals("CORRECT", butt.getText());
+ assertEquals(1, del.lookupAll(JButton.class).size());
+ assertEquals(1, merger.expectedCount);
+
+ pro3.ic.add(new JButton());
+ pro3.ic.add(new JRadioButton());
+ provInst.add(pro3);
+ assertNotNull(del.lookup(JRadioButton.class));
+
+ assertEquals("A change delivered", 1, jradioButtonListener.cnt);
+ }
+
+ private static class LookupMergerImpl implements LookupMerger<JButton> {
+
+ int expectedCount;
+
+ @Override public Class<JButton> getMergeableClass() {
+ return JButton.class;
+ }
+
+ @Override public JButton merge(final Lookup lookup) {
+ expectedCount = lookup.lookupAll(JButton.class).size();
+ lookup.lookupResult(JButton.class).addLookupListener(new LookupListener() {
+ public @Override void resultChanged(LookupEvent ev) {
+ expectedCount = lookup.lookupAll(JButton.class).size();
+ }
+ });
+ return new JButton("CORRECT");
+ }
+
+ }
+
+ private static class LookupProviderImpl implements LookupProvider {
+ InstanceContent ic = new InstanceContent();
+ boolean wasAlreadyCalled = false;
+ @Override public Lookup createAdditionalLookup(Lookup baseContext) {
+ assertNotNull(baseContext.lookup(JButton.class));
+ assertNull(baseContext.lookup(JCheckBox.class));
+ assertFalse(wasAlreadyCalled);
+ wasAlreadyCalled = true;
+ return new AbstractLookup(ic);
+ }
+ }
+
+}
diff --git a/nb/ide.launcher/netbeans.conf b/nb/ide.launcher/netbeans.conf
index edc8226..c12595e 100644
--- a/nb/ide.launcher/netbeans.conf
+++ b/nb/ide.launcher/netbeans.conf
@@ -63,7 +63,7 @@
# (see: https://issues.apache.org/jira/browse/NETBEANS-1344)
#
-netbeans_default_options="-J-XX:+UseStringDeduplication -J-Xss2m @@metabuild.logcli@@ -J-Dapple.laf.useScreenMenuBar=true -J-Dapple.awt.graphics.UseQuartz=true -J-Dsun.java2d.noddraw=true -J-Dsun.java2d.dpiaware=true -J-Dsun.zip.disableMemoryMapping=true -J-Dplugin.manager.check.updates=false -J-Dnetbeans.extbrowser.manual_chrome_plugin_install=yes -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.base/java.lang.ref=ALL-UNNAMED -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.security=ALL-UNNAMED -J--add-opens=java.base/java.util=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.basic=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.text=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=java.desktop/java.awt=ALL-UNNAMED -J--add-opens=java.desktop/java.awt.event=ALL-UNNAMED -J--add-opens=java.prefs/java.util.prefs=ALL-UNNAMED -J--add-opens=jdk.jshell/jdk.jshell=ALL-UNNAMED -J--add-modules=jdk.jshell -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED -J--add-exports=java.desktop/com.sun.beans.editors=ALL-UNNAMED -J--add-exports=java.desktop/sun.swing=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt.im=ALL-UNNAMED -J--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED -J--add-exports=java.management/sun.management=ALL-UNNAMED -J--add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED -J--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED -J-XX:+IgnoreUnrecognizedVMOptions"
+netbeans_default_options="-J-XX:+UseStringDeduplication -J-Xss2m @@metabuild.logcli@@ -J-Dapple.laf.useScreenMenuBar=true -J-Dapple.awt.graphics.UseQuartz=true -J-Dsun.java2d.noddraw=true -J-Dsun.java2d.dpiaware=true -J-Dsun.zip.disableMemoryMapping=true -J-Dplugin.manager.check.updates=false -J-Dnetbeans.extbrowser.manual_chrome_plugin_install=yes -J--add-opens=java.base/java.net=ALL-UNNAMED -J--add-opens=java.base/java.lang.ref=ALL-UNNAMED -J--add-opens=java.base/java.lang=ALL-UNNAMED -J--add-opens=java.base/java.security=ALL-UNNAMED -J--add-opens=java.base/java.util=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.basic=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.text=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing=ALL-UNNAMED -J--add-opens=java.desktop/java.awt=ALL-UNNAMED -J--add-opens=java.desktop/java.awt.event=ALL-UNNAMED -J--add-opens=java.prefs/java.util.prefs=ALL-UNNAMED -J--add-opens=jdk.jshell/jdk.jshell=ALL-UNNAMED -J--add-modules=jdk.jshell -J--add-exports=java.desktop/sun.awt=ALL-UNNAMED -J--add-exports=java.desktop/java.awt.peer=ALL-UNNAMED -J--add-exports=java.desktop/com.sun.beans.editors=ALL-UNNAMED -J--add-exports=java.desktop/sun.swing=ALL-UNNAMED -J--add-exports=java.desktop/sun.awt.im=ALL-UNNAMED -J--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED -J--add-exports=java.management/sun.management=ALL-UNNAMED -J--add-exports=java.base/sun.reflect.annotation=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED -J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED -J--add-exports=jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED -J--add-opens=java.desktop/sun.awt.X11=ALL-UNNAMED -J--add-opens=java.desktop/javax.swing.plaf.synth=ALL-UNNAMED -J--add-opens=java.desktop/com.sun.java.swing.plaf.gtk=ALL-UNNAMED -J--add-opens=java.desktop/sun.awt.shell=ALL-UNNAMED -J--add-opens=java.desktop/sun.awt.im=ALL-UNNAMED -J--add-opens=java.base/java.nio=ALL-UNNAMED -J-XX:+IgnoreUnrecognizedVMOptions"
# Default location of JDK:
# (set by installer or commented out if launcher should decide)