netbeans icon indicating copy to clipboard operation
netbeans copied to clipboard

Java Debugger: not working "apply code changes" if "compile on save" mode is enabled in the project

Open steelswing opened this issue 3 years ago • 19 comments

Apache NetBeans version

Apache NetBeans 12.6

What happened

I am developing large projects using Apache netbeans 12.6. When using debugger in netbeans 8.2, everything worked fine, but starting from version 8.2 above, the "Apply code changes" button stopped working if the "Compile on save" option is enabled in the project, and when saving the file (ctrl+s), code changes are not applied. I have been waiting since 2019 for a solution to this problem :)

in the IDE settings, the checkbox "Apply code changes after save (in "Compile on Save" mode only)" is enabled.

How to reproduce

Create empty ANT project, turn off "compile on save" in project settings, run this project as Debug.

For example, try this code

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws InterruptedException {
        // TODO code application logic here
    
    
        while (true) {            
            Thread.sleep(1000);
            System.out.println("Hello, Oracle  ");
        }
    }

Try changing the string "Hello Oracle" to something else in debug mode and the string does not apply, but in Netbeans 8.2 it worked fine

Did this work correctly in an earlier version?

No

Operating System

Windows 10 x64

JDK

JDK8

Apache NetBeans packaging

Apache NetBeans provided installer

Anything else

No response

Are you willing to submit a pull request?

No response

Code of Conduct

Yes

steelswing avatar Mar 03 '22 04:03 steelswing

Does the "Apply code changes" button in the debugging toolbar work? image

dstutz avatar Mar 07 '22 14:03 dstutz

Does the "Apply code changes" button in the debugging toolbar work? image

This button is not active in the "compile on save" mode

steelswing avatar Mar 08 '22 03:03 steelswing

I found some bug which is at least part of the problem. With b2fa5764338c5450bcd7f24005f5352d601c160d the reload class is triggered SourcePathProviderImpl but there is still a problem why it's not applied.

asbachb avatar May 19 '22 23:05 asbachb

I wonder if this functionality is totally broken. I could not get it work for maven projects either. Can someone double check if he gets code change work somehow?

asbachb avatar May 21 '22 09:05 asbachb

I wonder if this functionality is totally broken. I could not get it work for maven projects either. Can someone double check if he gets code change work somehow?

JPDA is not working on ANT project in the "Compile on Save" mode

steelswing avatar May 24 '22 18:05 steelswing

As I said. I cannot get this to work in Maven either.

asbachb avatar May 24 '22 18:05 asbachb

Have any idea what this is related to? :) I have been waiting since 2019 for a solution to this problem :)

steelswing avatar May 21 '25 02:05 steelswing

The problem is that the file does not compile on save when the 'Compile on Save' option is enabled and the program is running in debugging mode.

steelswing avatar Nov 07 '25 11:11 steelswing

If everything works correctly with Compile on Save off, then turn off Compile on Save.

neilcsmith-net avatar Nov 07 '25 11:11 neilcsmith-net

How do you like the decision to just not use the IDE? XD

If everything works correctly with Compile on Save off, then turn off Compile on Save.

steelswing avatar Nov 07 '25 12:11 steelswing

In general, the code indexer does not work properly if there is a running process launched through the IDE, even when it is not in Debug mode. As a workaround, there is a solution: do not run the application through the IDE, and instead connect to it separately via a port — this workaround works for me.

steelswing avatar Nov 07 '25 13:11 steelswing

If you look closely, then with any process running, saving a Java file does not trigger compilation, and the updated class does not appear in the 'build' folder. Because of this, the JPDA Debugger cannot apply the changes — the changes simply do not exist, since the file is not being compiled even though it was saved in the IDE.

UPD:

Operating System Windows 10 x64

Apache NetBeans 27

Well, as it turned out, this problem exists in all versions — I even tested it on NetBeans 8.2.

steelswing avatar Nov 07 '25 13:11 steelswing

How do you like the decision to just not use the IDE? XD

If everything works correctly with Compile on Save off, then turn off Compile on Save.

I've no idea what the point of this passive aggressive response is meant to be?!

Compile on Save is effectively deprecated, in the sense that no-one is actively working on fixing numerous issues with it. It was (for a short point) marked deprecated in the UI for NB27 in #8566 , at least for Maven. That UI change was reverted pending further discussion, but that doesn't mean the state of it is any better.

The short answer is that if you can't get "Apply Code Changes" to work for your workflow while "Compile on Save" is enabled, then disable CoS. If you cannot get changes to apply with CoS disabled, open a bug for that.

neilcsmith-net avatar Nov 07 '25 14:11 neilcsmith-net

How do you like the decision to just not use the IDE? XD

If everything works correctly with Compile on Save off, then turn off Compile on Save.

I've no idea what the point of this passive aggressive response is meant to be?!

Compile on Save is effectively deprecated, in the sense that no-one is actively working on fixing numerous issues with it. It was (for a short point) marked deprecated in the UI for NB27 in #8566 , at least for Maven. That UI change was reverted pending further discussion, but that doesn't mean the state of it is any better.

The short answer is that if you can't get "Apply Code Changes" to work for your workflow while "Compile on Save" is enabled, then disable CoS. If you cannot get changes to apply with CoS disabled, open a bug for that.

So you're suggesting turning off the very feature that basically gives this IDE its whole purpose, calling it outdated, and instead waiting every time while a single modified line of code takes 30 seconds to rebuild with Ant — or even worse, with Gradle or Maven, where it definitely takes longer than 30 seconds? I use this IDE specifically because it lets me apply code changes instantly on the fly, unlike other IDEs that don’t rely on an integrated compiler 🤡

steelswing avatar Nov 07 '25 23:11 steelswing

Since version 8.1, this has not working, the latest working version is NetBeans 8.0.2

steelswing avatar Nov 08 '25 00:11 steelswing

I found the problem. Module parsing.indexing (Parsing API Indexing)

Class parsing.indexing\src\org\netbeans\modules\parsing\impl\indexing\RepositoryUpdater.java

The protectedOwners.isEmpty() return false because it contains 'null'


Line ~5954

if (!scheduled && (protectedOwners.isEmpty() || offProtectedMode == Thread.currentThread())) {
    scheduled = true;
    LOGGER.fine("scheduled = true");    //NOI18N
    WORKER.submit(this);
}
waitForWork = wait;

My solution is probably wrong because I am not familiar with the internal structure of the IDE, but still it solves this problem.

protectedOwners.removeIf(Objects::isNull); // <-- fix
if (!scheduled && (protectedOwners.isEmpty() || offProtectedMode == Thread.currentThread())) {
    scheduled = true;
    LOGGER.fine("scheduled = true");    //NOI18N
    WORKER.submit(this);
}
waitForWork = wait;

@mbien What do you think?

steelswing avatar Nov 08 '25 02:11 steelswing

unfortunately I am not super interested in the cos feature due to its complexity, invasivenes into the project build and limited usefulness on more modern build systems (which are the better place to implement such feature IMO).

But looking at the code, null seems to be a valid value for the list, some usages add it explicitly. So removing null entries is likely not the answer and will cause other side effects.

mbien avatar Nov 08 '25 02:11 mbien

unfortunately I am not super interested in the cos feature due to its complexity, invasivenes into the project build and limited usefulness on more modern build systems (which are the better place to implement such feature IMO).

But looking at the code, null seems to be a valid value for the list, some usages add it explicitly. So removing null entries is likely not the answer and will cause other side effects.

The point is that the problem isn’t even specifically about Compile On Save. It’s the code indexer itself that stops working properly whenever there is a running process inside the IDE.

steelswing avatar Nov 08 '25 03:11 steelswing

I found some bug which is at least part of the problem. With b2fa5764338c5450bcd7f24005f5352d601c160d the reload class is triggered SourcePathProviderImpl but there is still a problem why it's not applied.

Java 8 projects not work because contains ';' separator in classpath

Original:

tring listeningCP = (String) properties.get("listeningCP");
            if (listeningCP != null) {
                boolean isSourcepath = false;
                if ("sourcepath".equalsIgnoreCase(listeningCP)) {
                    listeningCP = ((ClassPath) properties.get ("sourcepath")).toString(ClassPath.PathConversionMode.SKIP);
                    isSourcepath = true;
                }
                srcRootsToListenForArtifactsUpdates = new HashSet<FileObject>();
                for (String cp : listeningCP.split(File.pathSeparator)) {
                    logger.log(Level.FINE, "Listening cp = ''{0}''", cp);

My fix:

            String sourcepathSeperator = ",";
            
            String listeningCP = (String) properties.get("listeningCP");
            if (listeningCP != null) {
                boolean isSourcepath = false;
                if ("sourcepath".equalsIgnoreCase(listeningCP)) {
                    sourcepathSeperator = File.pathSeparator;
                    listeningCP = ((ClassPath) properties.get("sourcepath")).toString(ClassPath.PathConversionMode.SKIP);
                    isSourcepath = true;
                }
                srcRootsToListenForArtifactsUpdates = new HashSet<FileObject>();
                
                // fix
                List<String> paths = new ArrayList<>();
                final String[] split = listeningCP.split(sourcepathSeperator);
                paths.addAll(Arrays.asList(split));
                for (String string : listeningCP.split(";")) {
                    list.add(string.replace(",", ""));
                }

                for (String cp : paths) {
                    logger.log(Level.FINE, "Listening cp = ''{0}''", cp);

steelswing avatar Nov 08 '25 04:11 steelswing