|
|
|
|
|
|
|
org.netbeans
and org.netbeans.core
packages
which directly support early startup features, such as command-line
options.
Question (arch-overall):
Describe the overall architecture.
Answer:
The heart of NetBeans Runtime Container. Handles lifecycle of installed modules and OSGi bundles.
Question (arch-usecases): Describe the main use cases of the new API. Who will use it under what circumstances? What kind of code would typically need to be written to use the module? Answer:NetBeans Module system is optimized to eliminate useless I/O operations on start (as a result the embedded OSGi container is fastest on the planet -- with respect to application start up time). This is achieved by caching information known to have been needed in previous starts and using it rather than obtaining it again from the module JAR files.
There are various caches (like all-layers.dat, all-manifests.dat, all-resources.dat, netigso-bundles, etc. ) provided by the module system or by other subsystems of the application. Together, working in orchestration, they eliminate the need to touch the disk (which is very slow operation especially during morning launch). Btw. there is a test which verifies the caching system really works -- it is recommended for each product built on top of NetBeans Platform to copy and adjust it to verify the caches are really used.
Of course, the caches may get out of date, for example when an external tool modifies the installation layout. How can the system detect whether the caches are valid and still be usable? The only way to verify the caches are 100% correct is to regenerate them and compare whether the cached bits are the same. However that would be terribly slow and defeat the whole purpose of using caches.
As such we have the lastModified API.
Every cluster (as enumerated by netbeans.dirs
and netbeans.home properties)
is supposed to contain such file. Whenever an external tool changes something
inside some cluster, it is supposed to touch the file and change its
timestamp. That will tell the system that caches are invalid
(as their timestamps will become older than newest .lastModified
file).
The caches (as introduced in invalidating caches section) are optimized to reflect the state of previous start. However that means, the very first start runs without them. This may not be a problem (if the start follows immediately after installation), however in multi user environment (when the installation is done by administrator), the first start may be slow.
To mitigate that the system offers support for shared caches. As part of installation, one can also copy certain cache files into the shared location. Those files will then be used on a first start of the system (when the user directory is empty).
To generate the shared cache files start NetBeans with an empty, temporary user directory and then copy the desired files into first cluster directory:
$ netbeans --userdir /tmp/nb -J-Dnetbeans.close=true -J-Dorg.netbeans.core.WindowSystem.show=false $ cd /tmp/nb $ zip -r $INSTALL/$first_netbeans_dirs_dir/var/cache/populate.zip var/cache/netigso $ cp var/cache/* $INSTALL/$first_netbeans_dirs_dir/var/cache $ rm -r /tmp/nb/
The meaning of populate.zip
and list of known cache
files is described here.
Additional modules and subsystems may add new files however. The
ultimate knowledge is available only to those who understand overall
product installation structure.
In case one wants to modify other classes before they get loaded into
the VM, one can register its own
Agent-Class
and then be called whenever another
class is defined. The behavior matches as closely as possible the one
provided by
JDK instrument package. To patch bytecode of other classes
register your class in manifest and in its static agentmain
method
add your own ClassFileTransformer
which will then be consulted whenever new classes are loaded.
# following line should be in manifest of your module Agent-Class: your.pkg.Transformer // this should be your class package your.pkg; public class Transformer implements ClassFileTransformer { public static void agentmain(String args, Instrumentation i) { i.addTransformer(new Transformer()); } public byte[] transform( ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer ) { // do your transformation } }
The implementation tries to be as complient as possible with the
original JDK's specification, but
some differences are inevitable. For example the classBeingRedefined
parameter in the previous example is always null
as NetBeans runtime container does not
have access to the class instance that is being defined yet.
This is a specific case of Patch Classes use-case. To maintain binary compatibility when removing methods from API classes, the "removed" implementation is actually moved to a special class, which becomes a superclass of the original API class. Such special classes should be separated into a 'compat' module, which is only loaded in presence of old clients.
The compat module should declare it is a fragment of the original API module in its
MANIFEST.MF
OpenIDE-Module-Fragment-Host: orignal.module.codename
which ensures contents of the compat module will be loaded using classloader of the 'fragment host' module. The compat module will not get its own classloader. The special class itself should be marked using PatchFor annotation, which causes it will be patched as superclass and inserted into the inheritance chain.
Question (arch-time): What are the time estimates of the work? Answer:XXX no answer for arch-time
Question (arch-quality): How will the quality of your code be tested and how are future regressions going to be prevented? Answer:XXX no answer for arch-quality
Question (arch-where): Where one can find sources for your module? Answer:
The sources for the module are in the Apache Git repositories or in the GitHub repositories.
The nbexec launcher is fully featured and supported. It should work on any Unix flavor. Implemented as a shell script.
lock-file
-
The lock file ${netbeans.user}/lock will have file
permissions changed to go-rwx for safety on Unix
systems (requires presence of chmod
)
The nbexec.exe launcher is fully featured and supported. Implemented using Visual C++; prebuilt binary is kept in CVS along with sources.
org.netbeans.TopSecurityManager
.
Modules may use org.netbeans.CLIHandler
to add command-line
option handling (currently used by utilities
).
Question (deploy-dependencies):
What do other modules need to do to declare a dependency on this one,
in addition to or instead of the normal module dependency declaration
(e.g. tokens to require)?
Answer:
XXX no answer for deploy-dependencies
XXX no answer for compat-deprecation
java.io.File
directly?
Answer:
Yes, it must. The Filesystems API has not been loaded when it runs.
.lastModified
-
To speedup testing that module caches are up-to-date, the system
recognizes special file inside of each cluster. If .lastModified
file is present in a cluster, then the content of the cluster is not
scanned any more deeply and instead the time stamp of the file is
used as last modification for the whole content of the cluster.
This API is primarily intended for use by installer and RPM packagers and also autoupdate, that are supposed to create such file, as soon as they finish modifications to any cluster.
This file is ignored when accessing user directory, as it is expected that user can modify it, while the user usually does not have access permision or need to modify the shared installation clusters.
cached.lastModified -
If the .lastModified
file is not present in cluster
directory, it is recomputed on startup and stored in
$userdir/var/cache/lastModified/$clustername
. This
file and its content is meant just for private consumption of the
IDE.
Installer can speed NetBeans IDE start by generating caches when the
installation is over. Such caches are stored in the installation,
in first cluster listed by
netbeans.dirs
(or in a location specified by
netbeans.fallback.cache property, if available)
and have the same layout as user caches
(including here in described caches like all-resources.dat,
as well as caches provided by other subsystems like
netigso-bundles)
in the user directory - e.g. they are under var/cache
.
If a file var/cache/populate.zip
is found, its
content is unzipped into user directory (if it is empty).
To speedup class loading during startup, the system keeps a cache of resources needed during startup in var/cache/all-resources.dat. If the cache is valid, it is loaded during startup and class and resource loading requests are redirected there.
The file is binary and shouldn't be modified by other code than
org.netbeans.Archive
. The file content uses magic header
and versioning to allow evolution of its (private) format.
The location is however well known for
purposes of installer.
Rather than seeking on disk and using access
OS call uselessly
to find that some file is not present, the layout of files under
the clusters is recorded in var/cache/all-files.data
.
The file is binary and its format is private. The location is however well known for purposes of installer.
all-layers.dat -
Modules register their functionality into the system using
layers.
To avoid parsing and merging of content of these files on each start,
the system creates a cached, binary representation of the layers
structure in var/cache/all-layers.dat
and
var/cache/all-local-layers.dat
.
The file is binary and its format is private. The location is however well known for purposes of installer.
all-clusters.dat -Lists relative paths of clusters (those defined by netbeans.home and netbeans.dirs) for which the cache has been created. This is an important file in the shared cache as it helps to ensure the set of clusters has not changed since the cache has been generated.
The file is binary and its format is private. The location is however well known for purposes of installer.
all-installer.dat -
Additional information about modules (like deprecation message, etc.)
is stored in var/cache/all-installer.dat
to avoid the need
to parse it out on each start.
The file is binary and its format is private. The location is however well known for purposes of installer.
all-manifests.dat -
Graph of dependencies between modules, sorted startup order,
state of modules
is stored in var/cache/all-manifests.dat
to avoid the need
to compute this information on every start.
The file is binary and its format is private. The location is however well known for purposes of installer.
all-modules.dat -
Pre-parsed content of config/Modules/*.xml
is cached in var/cache/all-modules.dat
.
The file is binary and its format is private. The location is however well known for purposes of installer.
package-attrs.dat -
Cache of various attributes of packages (vendor, spec & impl version, etc.)
is stored in var/cache/package-attrs.dat
. This
file is often almost empty to signal such information
is not provided by any module.
The file is binary and its format is private. The location is however well known for purposes of installer.
localeVariants -
File var/cache/localeVariants
contains information
about used branding and L10N files for each module. Avoids checking
for locale/xyz_cs_CZ.jar
files when (for example) only English
L10N are present.
The file is binary and its format is private. The location is however well known for purposes of installer.
One can control creation of the all-resources.dat
file in
the user directory via
org.netbeans.core.update.all.resources
property.
XXX no answer for resources-preferences
org.openide.util.Lookup
or any similar technology to find any components to communicate with? Which ones?
Answer:
lookup.org.netbeans.CLIHandler
-
Instances of org.netbeans.CLIHandler
are found using
services lookup in the "dynamic classpath loader" (i.e. startup
classpath plus ${netbeans.home}/core/*.jar).
Instances of org.netbeans.ModuleFactory
are found using
services lookup in the "dynamic classpath loader" (i.e. startup
classpath plus ${netbeans.home}/core/*.jar). ModuleFactory
can be used to create alternative module implementations.
The communication between core.jar
and rest of the platform code
in org-netbeans-core.jar
is handled thru
handled thru CoreBridge
calls.
Additional callbacks from core.jar
after the module system is started
are done using RunLevel
interface. Currently it starts window system.
There is a communication bridge between the default logging handler registered by core/startup and the UI handler in core that presents certain log records in the UI.
Question (lookup-register): Do you register anything into lookup for other code to find? Answer: No. Question (lookup-remove): Do you remove entries of other modules from lookup? Answer: No.System.getProperty
) property?
On a similar note, is there something interesting that you
pass to java.util.logging.Logger
? Or do you observe
what others log?
Answer:
Software\JavaSoft\Java Development Kit
is the
default JDK installation directory to use, unless
--jdkhome is given. [Windows only]
org.netbeans.core.startup.Main
).
Might be used by alternate launchers.
Software\netbeans.org\NetBeans IDE\Dev
Default user directory, unless --userdir is
given. The name of this registry key is brandable, as is its
default value. [Windows only]
user.dir
.
none
,
then the fallback cache check is completely disabled.
"netbeans.patches." + module.getCodeNameBase()
one can influence installed modules without changing the build.
Format is -Dnetbeans.patches.org.nb.mods.foo=/path/to.file.jar:/path/to/dir
.
WARNING
level about accessing resources from the default package.
core/*.jar
files has been initialized
and the user dir has not yet been updated (see bellow) the
launcher checks for value of netbeans.importclass
system property and if provided it loads that class and invokes
its main method (in AWT thread) and if no exception is thrown it
marks the userdir as already upgraded.
imported-marker
-
${netbeans.user}/var/imported is used to identify whether a userdir has already been updated
or it still needs an update. Can be created by installer if no update
check should be performed, no other code is supposed to realy on
this file.
netbeans.accept_license_class
-
Before first usage of IDE user must accept license. If user does not install IDE
by installer (user must accept license during installation) user must accept license
during IDE first start.
Launcher calls method showLicensePanel
of netbeans.acceptlicenseclass
if license was not yet accepted by user and it is necessary to show license
in dialog to user.
Controls whether to log messages to the console, or just to the log file.
Setting this property to less than zero value enables logging of what is
going on in the CLIHandler - e.g. in the code that locks user directory and
handles processing of command line options. Use -J-Dorg.netbeans.CLIHandler=-1
to send the logging to System.err
.
One can disable the CLI server (listening on commands
from subsequent invocations) by setting property
org.netbeans.CLIHandler.server
to false
.
Contains class name of a class that can serve as provider of the writable layer of the
system file system. The class must be a subclass of
org.openide.filesystems.FileSystem
and have public default constructor.
Morevoer the class denoted by the property must be on the classpath.
System.exit
.
One can disable this behavior by providing -Dnetbeans.security.nocheck=true
.
Since version 2.47 such property also allows the SecurityManager
to be replaced by another.
getContent()
method of ExClipboard
waits to synchronize with system clipboard. Defaults to 1000ms.
DuplicateException
when an attempt is made
to load an already loaded module.
One can change this behavior by providing -Dnetbeans.ignore.dupmodule=true
since version 2.63. When -Dnetbeans.ignore.dupmodule=true
is provided,
attempt of duplicate loading is logged instead of throwing DuplicateException
.
There are also some options passed to the launcher (interpreted
either by the script itself, or by early startup Java code).
Options parsed by plugins using org.netbeans.CLIHandler
(e.g. -open FILE) are not included in this list:
netbeans.dirs
.
Some of the branded keys may also be of some interest, they are
enumerated under the property group, but all of them are currently
part of org/netbeans/core/startup/Bundle.properties
file and thus
can be branded by overriding them in
org/netbeans/core/startup/Bundle_brandingname.properties
true
or false
, allows
some applications build on top of the platform to disable
splash by default
DialogDisplayer
.
netbeans.exception.alert.min.level
-
Minimum integer level that triggers the blinking icon signaling an
exceptional state. By default 900 - e.g. WARNING.
netbeans.exception.report.min.level
-
Minimum integer level that triggers the dialog with exception.
By default 900 with assertions on and 1001 without them.
Question (exec-ant-tasks):
Do you define or register any ant tasks that other can use?
Answer:
XXX no answer for exec-ant-tasks
Question (exec-classloader): Does your code create its own class loader(s)? Answer: ClassPath-Composition - Bootstrap code creates a class loader to load the rest of the core from. The bootstrap code is loaded from the Java application class loader, using the classpath lib/*.jar. Dynamic-ClassPath-Composition - After creating bootstrap classpath another low level set of JARs is loaded with a new classloader from core/*.jar directories in each clusters. Question (exec-reflection): Does your code use Java Reflection to execute other code? Answer:The bootstrap code of course uses reflection to start the normal core. Currently some reflection is used in bootstrap class loaders to work around a variety of JRE bugs in handling loading from JAR files, especially on Windows which has mandatory file locking - the JRE code to load from JARs is rather buggy when it comes to changing or removing the JAR during the JVM session.
Javeleon -When present as a Java agent on the boot classpath, Javeleon is invoked reflectively to enhance module reloading.
Question (exec-privateaccess): Are you aware of any other parts of the system calling some of your methods by reflection? Answer: None known. Question (exec-process): Do you execute an external process from your module? How do you ensure that the result is the same on different platforms? Do you parse output? Do you depend on result code? Answer: No, except for the updater tool (part of Auto Update, q.v.).chmod
is run if available to disable read access for other users
to ${netbeans.user}/lock; no output is parsed but the result
code is checked (if the executable in fact exists).
Question (exec-introspection):
Does your module use any kind of runtime type information (instanceof
,
work with java.lang.Class
, etc.)?
Answer:
ProxyClassLoader
(the general NetBeans class loader which
loads all of core and modules) checks to see if its parent loaders
include instances of ProxyClassLoader
, in which case it
delegates to them differently. This is necessary due to the design of
that loader.
ExceptionAnnotatableUsingLogRecords
-
To support classification of exceptions and also annotation of
exceptions with logging levels and additional localized messages,
logged exceptions and their initCause's are searched for
implementation of Callable<LogRecord[]>
.
If an exception implements this interface, the call()
method is called and returned LogRecords
then
scanned for messages, levels, etc.
XXX no answer for exec-threading
Question (security-policy): Does your functionality require modifications to the standard policy file? Answer:XXX no answer for security-policy
Question (security-grant): Does your code grant additional rights to some other code? Answer:XXX no answer for security-grant
java.awt.datatransfer.Transferable
?
Answer:
N/A
XXX no answer for perf-spi