For reference, here's an example the doesn't have the problem. It uses a GridLayout(0, 1) with congruent gaps and border. Resize the enclosing frame to see the effect. Experiment with Box(BoxLayout.Y_AXIS) as an alternative.
I suspect the original code (mis-)uses some combination of setXxxSize() or setBounds(), which will display the effect shown if the chosen Look & Feel has different geometry specified by the buttons' UI delegate.

import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** @see https://stackoverflow.com/a/31078625/230513 */
public class Buttons {
    private void display() {
        JFrame f = new JFrame("Buttons");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel p = new JPanel(new GridLayout(0, 1, 10, 10));
        p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        for (int i = 0; i < 3; i++) {
            p.add(new JButton("Button " + (i + 1)));
        }
        f.add(p);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
    public static void main(String[] args) {
        EventQueue.invokeLater(new Buttons()::display);
    }
}